mirror of
https://github.com/zxing/zxing.git
synced 2024-11-09 20:44:03 -08:00
New C# port from Suraj Supekar
git-svn-id: https://zxing.googlecode.com/svn/trunk@1202 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
d6fc2ae079
commit
d4efd44fb0
62
csharp/AssemblyInfo.cs
Executable file
62
csharp/AssemblyInfo.cs
Executable file
|
@ -0,0 +1,62 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// 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("")]
|
||||
|
||||
|
108
csharp/BarcodeFormat.cs
Executable file
108
csharp/BarcodeFormat.cs
Executable file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <summary> Enumerates barcode formats known to this package.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class BarcodeFormat
|
||||
{
|
||||
public System.String Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// No, we can't use an enum here. J2ME doesn't support it.
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'VALUES '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly System.Collections.Hashtable VALUES = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
|
||||
|
||||
/// <summary>QR Code 2D barcode format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'QR_CODE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat QR_CODE = new BarcodeFormat("QR_CODE");
|
||||
|
||||
/// <summary>DataMatrix 2D barcode format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'DATAMATRIX '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat DATAMATRIX = new BarcodeFormat("DATAMATRIX");
|
||||
|
||||
/// <summary>UPC-E 1D format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'UPC_E '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat UPC_E = new BarcodeFormat("UPC_E");
|
||||
|
||||
/// <summary>UPC-A 1D format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'UPC_A '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat UPC_A = new BarcodeFormat("UPC_A");
|
||||
|
||||
/// <summary>EAN-8 1D format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'EAN_8 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat EAN_8 = new BarcodeFormat("EAN_8");
|
||||
|
||||
/// <summary>EAN-13 1D format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'EAN_13 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat EAN_13 = new BarcodeFormat("EAN_13");
|
||||
|
||||
/// <summary>Code 128 1D format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'CODE_128 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat CODE_128 = new BarcodeFormat("CODE_128");
|
||||
|
||||
/// <summary>Code 39 1D format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'CODE_39 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat CODE_39 = new BarcodeFormat("CODE_39");
|
||||
|
||||
/// <summary>ITF (Interleaved Two of Five) 1D format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ITF '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat ITF = new BarcodeFormat("ITF");
|
||||
|
||||
/// <summary>PDF417 format. </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'PDF417 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly BarcodeFormat PDF417 = new BarcodeFormat("PDF417");
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'name '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String name;
|
||||
|
||||
private BarcodeFormat(System.String name)
|
||||
{
|
||||
this.name = name;
|
||||
VALUES[name] = this;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public static BarcodeFormat valueOf(System.String name)
|
||||
{
|
||||
BarcodeFormat format = (BarcodeFormat) VALUES[name];
|
||||
if (format == null)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
return format;
|
||||
}
|
||||
}
|
||||
}
|
93
csharp/Binarizer.cs
Executable file
93
csharp/Binarizer.cs
Executable file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 BitArray = com.google.zxing.common.BitArray;
|
||||
using BitMatrix = com.google.zxing.common.BitMatrix;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public abstract class Binarizer
|
||||
{
|
||||
virtual public LuminanceSource LuminanceSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
/// <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>
|
||||
public abstract BitMatrix BlackMatrix{get;}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'source '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private LuminanceSource source;
|
||||
|
||||
protected internal Binarizer(LuminanceSource source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new System.ArgumentException("Source must be non-null.");
|
||||
}
|
||||
this.source = 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>
|
||||
public abstract BitArray getBlackRow(int y, BitArray row);
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
161
csharp/BinaryBitmap.cs
Executable file
161
csharp/BinaryBitmap.cs
Executable file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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 BitArray = com.google.zxing.common.BitArray;
|
||||
using BitMatrix = com.google.zxing.common.BitMatrix;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class BinaryBitmap
|
||||
{
|
||||
/// <returns> The width of the bitmap.
|
||||
/// </returns>
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return binarizer.LuminanceSource.Width;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> The height of the bitmap.
|
||||
/// </returns>
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return binarizer.LuminanceSource.Height;
|
||||
}
|
||||
|
||||
}
|
||||
/// <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>
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> Whether this bitmap supports counter-clockwise rotation.
|
||||
/// </returns>
|
||||
public bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return binarizer.LuminanceSource.RotateSupported;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'binarizer '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private Binarizer binarizer;
|
||||
private BitMatrix matrix;
|
||||
|
||||
public BinaryBitmap(Binarizer binarizer)
|
||||
{
|
||||
if (binarizer == null)
|
||||
{
|
||||
throw new System.ArgumentException("Binarizer must be non-null.");
|
||||
}
|
||||
this.binarizer = binarizer;
|
||||
matrix = null;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public BitArray getBlackRow(int y, BitArray row)
|
||||
{
|
||||
return binarizer.getBlackRow(y, row);
|
||||
}
|
||||
|
||||
/// <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));
|
||||
}
|
||||
|
||||
/// <summary> Returns a new object with rotated image data. Only callable if 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));
|
||||
}
|
||||
}
|
||||
}
|
78
csharp/DecodeHintType.cs
Executable file
78
csharp/DecodeHintType.cs
Executable file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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;
|
||||
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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
/// <seealso cref="Reader.decode(BinaryBitmap,java.util.Hashtable)">
|
||||
/// </seealso>
|
||||
public sealed class DecodeHintType
|
||||
{
|
||||
|
||||
// No, we can't use an enum here. J2ME doesn't support it.
|
||||
|
||||
/// <summary> Unspecified, application-specific hint. Maps to an unspecified {@link Object}.</summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'OTHER '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly DecodeHintType OTHER = new DecodeHintType();
|
||||
|
||||
/// <summary> Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
|
||||
/// use {@link Boolean#TRUE}.
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'PURE_BARCODE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly DecodeHintType PURE_BARCODE = new DecodeHintType();
|
||||
|
||||
/// <summary> Image is known to be of one of a few possible formats.
|
||||
/// Maps to a {@link java.util.Vector} of {@link BarcodeFormat}s.
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'POSSIBLE_FORMATS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly DecodeHintType POSSIBLE_FORMATS = new DecodeHintType();
|
||||
|
||||
/// <summary> Spend more time to try to find a barcode; optimize for accuracy, not speed.
|
||||
/// Doesn't matter what it maps to; use {@link Boolean#TRUE}.
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'TRY_HARDER '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly DecodeHintType TRY_HARDER = new DecodeHintType();
|
||||
|
||||
/// <summary> Allowed lengths of encoded data -- reject anything else. Maps to an int[].</summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ALLOWED_LENGTHS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly DecodeHintType ALLOWED_LENGTHS = new DecodeHintType();
|
||||
|
||||
/// <summary> Assume Code 39 codes employ a check digit. Maps to {@link Boolean}.</summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ASSUME_CODE_39_CHECK_DIGIT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly DecodeHintType ASSUME_CODE_39_CHECK_DIGIT = new DecodeHintType();
|
||||
|
||||
/// <summary> The caller needs to be notified via callback when a possible {@link ResultPoint}
|
||||
/// is found. Maps to a {@link ResultPointCallback}.
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'NEED_RESULT_POINT_CALLBACK '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly DecodeHintType NEED_RESULT_POINT_CALLBACK = new DecodeHintType();
|
||||
|
||||
private DecodeHintType()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
43
csharp/EncodeHintType.cs
Executable file
43
csharp/EncodeHintType.cs
Executable file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <summary> These are a set of hints that you may pass to Writers to specify their behavior.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class EncodeHintType
|
||||
{
|
||||
|
||||
/// <summary> Specifies what degree of error correction to use, for example in QR Codes (type Integer).</summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ERROR_CORRECTION '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly EncodeHintType ERROR_CORRECTION = new EncodeHintType();
|
||||
|
||||
/// <summary> Specifies what character encoding to use where applicable (type String)</summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'CHARACTER_SET '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly EncodeHintType CHARACTER_SET = new EncodeHintType();
|
||||
|
||||
private EncodeHintType()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
140
csharp/LuminanceSource.cs
Executable file
140
csharp/LuminanceSource.cs
Executable file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* 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 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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public abstract class LuminanceSource
|
||||
{
|
||||
/// <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>
|
||||
virtual public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> The height of the bitmap.
|
||||
/// </returns>
|
||||
virtual public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> Whether this subclass supports cropping.
|
||||
/// </returns>
|
||||
virtual public bool CropSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> Whether this subclass supports counter-clockwise rotation.
|
||||
/// </returns>
|
||||
virtual public bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'width '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int width;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'height '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private 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> 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.SystemException("This luminance source does not support cropping.");
|
||||
}
|
||||
|
||||
/// <summary> Returns a new object with rotated image data. Only callable if isRotateSupported() is true.
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns> A rotated version of this object.
|
||||
/// </returns>
|
||||
public virtual LuminanceSource rotateCounterClockwise()
|
||||
{
|
||||
throw new System.SystemException("This luminance source does not support rotation.");
|
||||
}
|
||||
}
|
||||
}
|
175
csharp/MultiFormatReader.cs
Executable file
175
csharp/MultiFormatReader.cs
Executable file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* 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 MultiFormatOneDReader = com.google.zxing.oned.MultiFormatOneDReader;
|
||||
using PDF417Reader = com.google.zxing.pdf417.PDF417Reader;
|
||||
using QRCodeReader = com.google.zxing.qrcode.QRCodeReader;
|
||||
using DataMatrixReader = com.google.zxing.datamatrix.DataMatrixReader;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class MultiFormatReader : Reader
|
||||
{
|
||||
/// <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 System.Collections.Hashtable Hints
|
||||
{
|
||||
set
|
||||
{
|
||||
this.hints = value;
|
||||
|
||||
bool tryHarder = value != null && value.ContainsKey(DecodeHintType.TRY_HARDER);
|
||||
System.Collections.ArrayList formats = value == null?null:(System.Collections.ArrayList) value[DecodeHintType.POSSIBLE_FORMATS];
|
||||
readers = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
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.CODE_39) || formats.Contains(BarcodeFormat.CODE_128) || formats.Contains(BarcodeFormat.ITF);
|
||||
// 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.DATAMATRIX))
|
||||
{
|
||||
readers.Add(new DataMatrixReader());
|
||||
}
|
||||
if (formats.Contains(BarcodeFormat.PDF417))
|
||||
{
|
||||
readers.Add(new PDF417Reader());
|
||||
}
|
||||
// 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());
|
||||
|
||||
// TODO re-enable once Data Matrix is ready
|
||||
// readers.addElement(new DataMatrixReader());
|
||||
|
||||
// TODO: Enable once PDF417 has passed QA
|
||||
//readers.addElement(new PDF417Reader());
|
||||
|
||||
if (tryHarder)
|
||||
{
|
||||
readers.Add(new MultiFormatOneDReader(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private System.Collections.Hashtable hints;
|
||||
private System.Collections.ArrayList 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>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
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>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
public Result decode(BinaryBitmap image, System.Collections.Hashtable 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>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
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);
|
||||
}
|
||||
|
||||
private Result decodeInternal(BinaryBitmap image)
|
||||
{
|
||||
int size = readers.Count;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
Reader reader = (Reader) readers[i];
|
||||
try
|
||||
{
|
||||
return reader.decode(image, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
}
|
63
csharp/MultiFormatWriter.cs
Executable file
63
csharp/MultiFormatWriter.cs
Executable file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 ByteMatrix = com.google.zxing.common.ByteMatrix;
|
||||
using EAN13Writer = com.google.zxing.oned.EAN13Writer;
|
||||
using EAN8Writer = com.google.zxing.oned.EAN8Writer;
|
||||
using QRCodeWriter = com.google.zxing.qrcode.QRCodeWriter;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <summary> This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat
|
||||
/// requested and encodes the barcode with the supplied contents.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class MultiFormatWriter : Writer
|
||||
{
|
||||
|
||||
public ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height)
|
||||
{
|
||||
|
||||
return encode(contents, format, width, height, null);
|
||||
}
|
||||
|
||||
public ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height, System.Collections.Hashtable hints)
|
||||
{
|
||||
|
||||
if (format == BarcodeFormat.EAN_8)
|
||||
{
|
||||
return new EAN8Writer().encode(contents, format, width, height, hints);
|
||||
}
|
||||
else if (format == BarcodeFormat.EAN_13)
|
||||
{
|
||||
return new EAN13Writer().encode(contents, format, width, height, hints);
|
||||
}
|
||||
else if (format == BarcodeFormat.QR_CODE)
|
||||
{
|
||||
return new QRCodeWriter().encode(contents, format, width, height, hints);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.ArgumentException("No encoder available for format " + format);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
163
csharp/RGBLuminanceSource.cs
Executable file
163
csharp/RGBLuminanceSource.cs
Executable file
|
@ -0,0 +1,163 @@
|
|||
using com.google.zxing;
|
||||
using com.google.zxing.common;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Drawing;
|
||||
using System;
|
||||
|
||||
public class RGBLuminanceSource : LuminanceSource
|
||||
{
|
||||
|
||||
private sbyte[] luminances;
|
||||
private bool isRotated = false;
|
||||
private bool __isRegionSelect = false;
|
||||
private Rectangle __Region;
|
||||
|
||||
override public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!isRotated)
|
||||
return __height;
|
||||
else
|
||||
return __width;
|
||||
}
|
||||
|
||||
}
|
||||
override public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!isRotated)
|
||||
return __width;
|
||||
else
|
||||
return __height;
|
||||
}
|
||||
|
||||
}
|
||||
private int __height;
|
||||
private int __width;
|
||||
|
||||
public RGBLuminanceSource(byte[] d, int W, int H)
|
||||
: base(W, H)
|
||||
{
|
||||
__width = W;
|
||||
__height = H;
|
||||
int width = W;
|
||||
int height = 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];
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int r = d[offset * 3 + x * 3];
|
||||
int g = d[offset * 3 + x * 3 + 1];
|
||||
int b = d[offset * 3 + x * 3 + 2];
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public RGBLuminanceSource(byte[] d, int W, int H,bool Is8Bit)
|
||||
: base(W, H)
|
||||
{
|
||||
__width = W;
|
||||
__height = H;
|
||||
luminances = new sbyte[W * H];
|
||||
Buffer.BlockCopy(d,0, luminances,0, W * H);
|
||||
}
|
||||
|
||||
public RGBLuminanceSource(byte[] d, int W, int H, bool Is8Bit,Rectangle Region)
|
||||
: base(W, H)
|
||||
{
|
||||
__width = Region.Width;
|
||||
__height = Region.Height;
|
||||
__Region = Region;
|
||||
__isRegionSelect = true;
|
||||
//luminances = Red.Imaging.Filters.CropArea(d, W, H, Region);
|
||||
}
|
||||
|
||||
|
||||
public RGBLuminanceSource(Bitmap d, int W, int H)
|
||||
: base(W, H)
|
||||
{
|
||||
int width = __width = W;
|
||||
int height = __height = 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
override public sbyte[] getRow(int y, sbyte[] row)
|
||||
{
|
||||
if (isRotated == false)
|
||||
{
|
||||
int width = Width;
|
||||
if (row == null || row.Length < width)
|
||||
{
|
||||
row = new sbyte[width];
|
||||
}
|
||||
for (int i = 0; i < width; i++)
|
||||
row[i] = luminances[y * width + i];
|
||||
//System.arraycopy(luminances, y * width, row, 0, width);
|
||||
return row;
|
||||
}
|
||||
else
|
||||
{
|
||||
int width = __width;
|
||||
int height = __height;
|
||||
if (row == null || row.Length < height)
|
||||
{
|
||||
row = new sbyte[height];
|
||||
}
|
||||
for (int i = 0; i < height; i++)
|
||||
row[i] = luminances[i * width + y];
|
||||
//System.arraycopy(luminances, y * width, row, 0, width);
|
||||
return row;
|
||||
}
|
||||
}
|
||||
public override sbyte[] Matrix
|
||||
{
|
||||
get { return luminances; }
|
||||
}
|
||||
|
||||
public override LuminanceSource crop(int left, int top, int width, int height)
|
||||
{
|
||||
return base.crop(left, top, width, height);
|
||||
}
|
||||
public override LuminanceSource rotateCounterClockwise()
|
||||
{
|
||||
isRotated = true;
|
||||
return this;
|
||||
}
|
||||
public override bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
65
csharp/Reader.cs
Executable file
65
csharp/Reader.cs
Executable file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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;
|
||||
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, {@link 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 {@link com.google.zxing.MultiFormatReader}, which attempts to determine what barcode
|
||||
/// format is present within the image as well, and then decodes it accordingly.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
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>
|
||||
/// <throws> ReaderException if the barcode cannot be located or decoded for any reason </throws>
|
||||
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 {@link java.util.Hashtable} from {@link 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>
|
||||
/// <throws> ReaderException if the barcode cannot be located or decoded for any reason </throws>
|
||||
Result decode(BinaryBitmap image, System.Collections.Hashtable hints);
|
||||
}
|
||||
}
|
113
csharp/ReaderException.cs
Executable file
113
csharp/ReaderException.cs
Executable file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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;
|
||||
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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
[Serializable]
|
||||
public sealed class ReaderException:System.Exception
|
||||
{
|
||||
public static ReaderException Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
// Exception e = new Exception();
|
||||
// // Take the stack frame before this one.
|
||||
// StackTraceElement stack = e.getStackTrace()[1];
|
||||
// String key = stack.getClassName() + "." + stack.getMethodName() + "(), line " +
|
||||
// stack.getLineNumber();
|
||||
// if (throwers.containsKey(key)) {
|
||||
// Integer value = throwers.get(key);
|
||||
// value++;
|
||||
// throwers.put(key, value);
|
||||
// } else {
|
||||
// throwers.put(key, 1);
|
||||
// }
|
||||
// exceptionCount++;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Currently we throw up to 400 ReaderExceptions while scanning a single 240x240 image before
|
||||
// rejecting it. This involves a lot of overhead and memory allocation, and affects both performance
|
||||
// and latency on continuous scan clients. In the future, we should change all the decoders not to
|
||||
// throw exceptions for routine events, like not finding a barcode on a given row. Instead, we
|
||||
// should return error codes back to the callers, and simply delete this class. In the mean time, I
|
||||
// have altered this class to be as lightweight as possible, by ignoring the exception string, and
|
||||
// by disabling the generation of stack traces, which is especially time consuming. These are just
|
||||
// temporary measures, pending the big cleanup.
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'instance '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly ReaderException instance = new ReaderException();
|
||||
|
||||
// EXCEPTION TRACKING SUPPORT
|
||||
// Identifies who is throwing exceptions and how often. To use:
|
||||
//
|
||||
// 1. Uncomment these lines and the code below which uses them.
|
||||
// 2. Uncomment the two corresponding lines in j2se/CommandLineRunner.decode()
|
||||
// 3. Change core to build as Java 1.5 temporarily
|
||||
// private static int exceptionCount = 0;
|
||||
// private static Map<String,Integer> throwers = new HashMap<String,Integer>(32);
|
||||
|
||||
private ReaderException()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// public static int getExceptionCountAndReset() {
|
||||
// int temp = exceptionCount;
|
||||
// exceptionCount = 0;
|
||||
// return temp;
|
||||
// }
|
||||
//
|
||||
// public static String getThrowersAndReset() {
|
||||
// StringBuilder builder = new StringBuilder(1024);
|
||||
// Object[] keys = throwers.keySet().toArray();
|
||||
// for (int x = 0; x < keys.length; x++) {
|
||||
// String key = (String) keys[x];
|
||||
// Integer value = throwers.get(key);
|
||||
// builder.append(key);
|
||||
// builder.append(": ");
|
||||
// builder.append(value);
|
||||
// builder.append("\n");
|
||||
// }
|
||||
// throwers.clear();
|
||||
// return builder.toString();
|
||||
// }
|
||||
|
||||
// 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.
|
||||
//UPGRADE_NOTE: Exception 'java.lang.Throwable' was converted to 'System.Exception' which has different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1100'"
|
||||
//UPGRADE_NOTE: The equivalent of method 'java.lang.Throwable.fillInStackTrace' is not an override method. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1143'"
|
||||
public System.Exception fillInStackTrace()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
129
csharp/Result.cs
Executable file
129
csharp/Result.cs
Executable file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <summary> <p>Encapsulates the result of decoding a barcode within an image.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class Result
|
||||
{
|
||||
/// <returns> raw text encoded by the barcode, if applicable, otherwise <code>null</code>
|
||||
/// </returns>
|
||||
public System.String Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> raw bytes encoded by the barcode, if applicable, otherwise <code>null</code>
|
||||
/// </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> {@link BarcodeFormat} representing the format of the barcode that was decoded
|
||||
/// </returns>
|
||||
public BarcodeFormat BarcodeFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return format;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> {@link Hashtable} mapping {@link ResultMetadataType} keys to values. May be
|
||||
/// <code>null</code>. This contains optional metadata about what was detected about the barcode,
|
||||
/// like orientation.
|
||||
/// </returns>
|
||||
public System.Collections.Hashtable ResultMetadata
|
||||
{
|
||||
get
|
||||
{
|
||||
return resultMetadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'text '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String text;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'rawBytes '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private sbyte[] rawBytes;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'resultPoints '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ResultPoint[] resultPoints;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'format '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private BarcodeFormat format;
|
||||
private System.Collections.Hashtable resultMetadata;
|
||||
|
||||
public Result(System.String text, sbyte[] rawBytes, ResultPoint[] resultPoints, BarcodeFormat format)
|
||||
{
|
||||
if (text == null && rawBytes == null)
|
||||
{
|
||||
throw new System.ArgumentException("Text and bytes are null");
|
||||
}
|
||||
this.text = text;
|
||||
this.rawBytes = rawBytes;
|
||||
this.resultPoints = resultPoints;
|
||||
this.format = format;
|
||||
this.resultMetadata = null;
|
||||
}
|
||||
|
||||
public void putMetadata(ResultMetadataType type, System.Object value_Renamed)
|
||||
{
|
||||
if (resultMetadata == null)
|
||||
{
|
||||
resultMetadata = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(3));
|
||||
}
|
||||
resultMetadata[type] = value_Renamed;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
return "[" + rawBytes.Length + " bytes]";
|
||||
}
|
||||
else
|
||||
{
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
68
csharp/ResultMetadataType.cs
Executable file
68
csharp/ResultMetadataType.cs
Executable file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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;
|
||||
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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class ResultMetadataType
|
||||
{
|
||||
|
||||
// No, we can't use an enum here. J2ME doesn't support it.
|
||||
|
||||
/// <summary> Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.</summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'OTHER '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ResultMetadataType OTHER = new ResultMetadataType();
|
||||
|
||||
/// <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 {@link Integer} whose
|
||||
/// value is in the range [0,360).
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ORIENTATION '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ResultMetadataType ORIENTATION = new ResultMetadataType();
|
||||
|
||||
/// <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 {@link 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 {@link java.util.Vector} of byte arrays corresponding to the
|
||||
/// raw bytes in the byte segments in the barcode, in order.</p>
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'BYTE_SEGMENTS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ResultMetadataType BYTE_SEGMENTS = new ResultMetadataType();
|
||||
|
||||
/// <summary> Error correction level used, if applicable. The value type depends on the
|
||||
/// format, but is typically a String.
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ERROR_CORRECTION_LEVEL '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ResultMetadataType ERROR_CORRECTION_LEVEL = new ResultMetadataType();
|
||||
|
||||
private ResultMetadataType()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
157
csharp/ResultPoint.cs
Executable file
157
csharp/ResultPoint.cs
Executable file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public class ResultPoint
|
||||
{
|
||||
virtual public float X
|
||||
{
|
||||
get
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
}
|
||||
virtual public float Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'x '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private float x;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'y '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private float y;
|
||||
|
||||
public ResultPoint(float x, float y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public override bool Equals(System.Object other)
|
||||
{
|
||||
if (other is ResultPoint)
|
||||
{
|
||||
ResultPoint otherPoint = (ResultPoint) other;
|
||||
return x == otherPoint.x && y == otherPoint.y;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
// Redivivus.in Java to c# Porting update
|
||||
// 30/01/2010
|
||||
// Commented function body
|
||||
|
||||
//return 31 * Float.floatToIntBits(x) + Float.floatToIntBits(y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.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, pointB, 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)
|
||||
{
|
||||
float xDiff = pattern1.X - pattern2.X;
|
||||
float yDiff = pattern1.Y - pattern2.Y;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
return (float) System.Math.Sqrt((double) (xDiff * xDiff + yDiff * yDiff));
|
||||
}
|
||||
|
||||
/// <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));
|
||||
}
|
||||
}
|
||||
}
|
31
csharp/ResultPointCallback.cs
Executable file
31
csharp/ResultPointCallback.cs
Executable file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 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);
|
||||
}
|
||||
}
|
215
csharp/SupportClass.cs
Executable file
215
csharp/SupportClass.cs
Executable file
|
@ -0,0 +1,215 @@
|
|||
//
|
||||
// In order to convert some functionality to Visual C#, the Java Language Conversion Assistant
|
||||
// creates "support classes" that duplicate the original functionality.
|
||||
//
|
||||
// Support classes replicate the functionality of the original code, but in some cases they are
|
||||
// substantially different architecturally. Although every effort is made to preserve the
|
||||
// original architecture of the application in the converted project, the user should be aware that
|
||||
// the primary goal of these support classes is to replicate functionality, and that at times
|
||||
// the architecture of the resulting solution may differ somewhat.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Contains conversion support elements such as classes, interfaces and static methods.
|
||||
/// </summary>
|
||||
public class SupportClass
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an array of sbytes to an array of bytes
|
||||
/// </summary>
|
||||
/// <param name="sbyteArray">The array of sbytes to be converted</param>
|
||||
/// <returns>The new array of bytes</returns>
|
||||
public static byte[] ToByteArray(sbyte[] sbyteArray)
|
||||
{
|
||||
byte[] byteArray = null;
|
||||
|
||||
if (sbyteArray != null)
|
||||
{
|
||||
byteArray = new byte[sbyteArray.Length];
|
||||
for(int index=0; index < sbyteArray.Length; index++)
|
||||
byteArray[index] = (byte) sbyteArray[index];
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to an array of bytes
|
||||
/// </summary>
|
||||
/// <param name="sourceString">The string to be converted</param>
|
||||
/// <returns>The new array of bytes</returns>
|
||||
public static byte[] ToByteArray(System.String sourceString)
|
||||
{
|
||||
return System.Text.UTF8Encoding.UTF8.GetBytes(sourceString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a array of object-type instances to a byte-type array.
|
||||
/// </summary>
|
||||
/// <param name="tempObjectArray">Array to convert.</param>
|
||||
/// <returns>An array of byte type elements.</returns>
|
||||
public static byte[] ToByteArray(System.Object[] tempObjectArray)
|
||||
{
|
||||
byte[] byteArray = null;
|
||||
if (tempObjectArray != null)
|
||||
{
|
||||
byteArray = new byte[tempObjectArray.Length];
|
||||
for (int index = 0; index < tempObjectArray.Length; index++)
|
||||
byteArray[index] = (byte)tempObjectArray[index];
|
||||
}
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static int URShift(int number, int bits)
|
||||
{
|
||||
if ( number >= 0)
|
||||
return number >> bits;
|
||||
else
|
||||
return (number >> bits) + (2 << ~bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static int URShift(int number, long bits)
|
||||
{
|
||||
return URShift(number, (int)bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static long URShift(long number, int bits)
|
||||
{
|
||||
if ( number >= 0)
|
||||
return number >> bits;
|
||||
else
|
||||
return (number >> bits) + (2L << ~bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
public static long URShift(long number, long bits)
|
||||
{
|
||||
return URShift(number, (int)bits);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/// <summary>
|
||||
/// This method returns the literal value received
|
||||
/// </summary>
|
||||
/// <param name="literal">The literal to return</param>
|
||||
/// <returns>The received value</returns>
|
||||
public static long Identity(long literal)
|
||||
{
|
||||
return literal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns the literal value received
|
||||
/// </summary>
|
||||
/// <param name="literal">The literal to return</param>
|
||||
/// <returns>The received value</returns>
|
||||
public static ulong Identity(ulong literal)
|
||||
{
|
||||
return literal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns the literal value received
|
||||
/// </summary>
|
||||
/// <param name="literal">The literal to return</param>
|
||||
/// <returns>The received value</returns>
|
||||
public static float Identity(float literal)
|
||||
{
|
||||
return literal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns the literal value received
|
||||
/// </summary>
|
||||
/// <param name="literal">The literal to return</param>
|
||||
/// <returns>The received value</returns>
|
||||
public static double Identity(double literal)
|
||||
{
|
||||
return literal;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/// <summary>
|
||||
/// Copies an array of chars obtained from a String into a specified array of chars
|
||||
/// </summary>
|
||||
/// <param name="sourceString">The String to get the chars from</param>
|
||||
/// <param name="sourceStart">Position of the String to start getting the chars</param>
|
||||
/// <param name="sourceEnd">Position of the String to end getting the chars</param>
|
||||
/// <param name="destinationArray">Array to return the chars</param>
|
||||
/// <param name="destinationStart">Position of the destination array of chars to start storing the chars</param>
|
||||
/// <returns>An array of chars</returns>
|
||||
public static void GetCharsFromString(System.String sourceString, int sourceStart, int sourceEnd, char[] destinationArray, int destinationStart)
|
||||
{
|
||||
int sourceCounter;
|
||||
int destinationCounter;
|
||||
sourceCounter = sourceStart;
|
||||
destinationCounter = destinationStart;
|
||||
while (sourceCounter < sourceEnd)
|
||||
{
|
||||
destinationArray[destinationCounter] = (char) sourceString[sourceCounter];
|
||||
sourceCounter++;
|
||||
destinationCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/// <summary>
|
||||
/// Sets the capacity for the specified ArrayList
|
||||
/// </summary>
|
||||
/// <param name="vector">The ArrayList which capacity will be set</param>
|
||||
/// <param name="newCapacity">The new capacity value</param>
|
||||
public static void SetCapacity(System.Collections.ArrayList vector, int newCapacity)
|
||||
{
|
||||
if (newCapacity > vector.Count)
|
||||
vector.AddRange(new Array[newCapacity-vector.Count]);
|
||||
else if (newCapacity < vector.Count)
|
||||
vector.RemoveRange(newCapacity, vector.Count - newCapacity);
|
||||
vector.Capacity = newCapacity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************/
|
||||
/// <summary>
|
||||
/// Receives a byte array and returns it transformed in an sbyte array
|
||||
/// </summary>
|
||||
/// <param name="byteArray">Byte array to process</param>
|
||||
/// <returns>The transformed array</returns>
|
||||
public static sbyte[] ToSByteArray(byte[] byteArray)
|
||||
{
|
||||
sbyte[] sbyteArray = null;
|
||||
if (byteArray != null)
|
||||
{
|
||||
sbyteArray = new sbyte[byteArray.Length];
|
||||
for(int index=0; index < byteArray.Length; index++)
|
||||
sbyteArray[index] = (sbyte) byteArray[index];
|
||||
}
|
||||
return sbyteArray;
|
||||
}
|
||||
|
||||
}
|
62
csharp/Writer.cs
Executable file
62
csharp/Writer.cs
Executable file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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 ByteMatrix = com.google.zxing.common.ByteMatrix;
|
||||
namespace com.google.zxing
|
||||
{
|
||||
|
||||
/// <summary> The base class for all objects which encode/generate a barcode image.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
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>
|
||||
/// <returns> The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
|
||||
/// </returns>
|
||||
ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height);
|
||||
|
||||
/// <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>
|
||||
ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height, System.Collections.Hashtable hints);
|
||||
}
|
||||
}
|
40
csharp/WriterException.cs
Executable file
40
csharp/WriterException.cs
Executable file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
[Serializable]
|
||||
public sealed class WriterException:System.Exception
|
||||
{
|
||||
|
||||
public WriterException():base()
|
||||
{
|
||||
}
|
||||
|
||||
public WriterException(System.String message):base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
45
csharp/client/result/AbstractDoCoMoResultParser.cs
Executable file
45
csharp/client/result/AbstractDoCoMoResultParser.cs
Executable file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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;
|
||||
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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
abstract class AbstractDoCoMoResultParser:ResultParser
|
||||
{
|
||||
|
||||
internal static System.String[] matchDoCoMoPrefixedField(System.String prefix, System.String rawText, bool trim)
|
||||
{
|
||||
return matchPrefixedField(prefix, rawText, ';', trim);
|
||||
}
|
||||
|
||||
internal static System.String matchSingleDoCoMoPrefixedField(System.String prefix, System.String rawText, bool trim)
|
||||
{
|
||||
return matchSinglePrefixedField(prefix, rawText, ';', trim);
|
||||
}
|
||||
}
|
||||
}
|
79
csharp/client/result/AddressBookAUResultParser.cs
Executable file
79
csharp/client/result/AddressBookAUResultParser.cs
Executable file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.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!)
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class AddressBookAUResultParser:ResultParser
|
||||
{
|
||||
|
||||
public static AddressBookParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
// MEMORY is mandatory; seems like a decent indicator, as does end-of-record separator CR/LF
|
||||
if (rawText == null || rawText.IndexOf("MEMORY") < 0 || rawText.IndexOf("\r\n") < 0)
|
||||
{
|
||||
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.
|
||||
System.String name = matchSinglePrefixedField("NAME1:", rawText, '\r', true);
|
||||
System.String pronunciation = matchSinglePrefixedField("NAME2:", rawText, '\r', true);
|
||||
|
||||
System.String[] phoneNumbers = matchMultipleValuePrefix("TEL", 3, rawText, true);
|
||||
System.String[] emails = matchMultipleValuePrefix("MAIL", 3, rawText, true);
|
||||
System.String note = matchSinglePrefixedField("MEMORY:", rawText, '\r', false);
|
||||
System.String address = matchSinglePrefixedField("ADD:", rawText, '\r', true);
|
||||
System.String[] addresses = address == null?null:new System.String[]{address};
|
||||
return new AddressBookParsedResult(maybeWrap(name), pronunciation, phoneNumbers, emails, note, addresses, null, null, null, null);
|
||||
}
|
||||
|
||||
private static System.String[] matchMultipleValuePrefix(System.String prefix, int max, System.String rawText, bool trim)
|
||||
{
|
||||
System.Collections.ArrayList values = null;
|
||||
for (int i = 1; i <= max; i++)
|
||||
{
|
||||
System.String value_Renamed = matchSinglePrefixedField(prefix + i + ':', rawText, '\r', trim);
|
||||
if (value_Renamed == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (values == null)
|
||||
{
|
||||
values = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(max)); // lazy init
|
||||
}
|
||||
values.Add(value_Renamed);
|
||||
}
|
||||
if (values == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return toStringArray(values);
|
||||
}
|
||||
}
|
||||
}
|
85
csharp/client/result/AddressBookDoCoMoResultParser.cs
Executable file
85
csharp/client/result/AddressBookDoCoMoResultParser.cs
Executable file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.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
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class AddressBookDoCoMoResultParser:AbstractDoCoMoResultParser
|
||||
{
|
||||
|
||||
public static AddressBookParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("MECARD:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String[] rawName = matchDoCoMoPrefixedField("N:", rawText, true);
|
||||
if (rawName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String name = parseName(rawName[0]);
|
||||
System.String pronunciation = matchSingleDoCoMoPrefixedField("SOUND:", rawText, true);
|
||||
System.String[] phoneNumbers = matchDoCoMoPrefixedField("TEL:", rawText, true);
|
||||
System.String[] emails = matchDoCoMoPrefixedField("EMAIL:", rawText, true);
|
||||
System.String note = matchSingleDoCoMoPrefixedField("NOTE:", rawText, false);
|
||||
System.String[] addresses = matchDoCoMoPrefixedField("ADR:", rawText, true);
|
||||
System.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;
|
||||
}
|
||||
System.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.
|
||||
System.String org = matchSingleDoCoMoPrefixedField("ORG:", rawText, true);
|
||||
|
||||
return new AddressBookParsedResult(maybeWrap(name), pronunciation, phoneNumbers, emails, note, addresses, org, birthday, null, url);
|
||||
}
|
||||
|
||||
private static System.String parseName(System.String name)
|
||||
{
|
||||
int comma = name.IndexOf(',');
|
||||
if (comma >= 0)
|
||||
{
|
||||
// Format may be last,first; switch it around
|
||||
return name.Substring(comma + 1) + ' ' + name.Substring(0, (comma) - (0));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
169
csharp/client/result/AddressBookParsedResult.cs
Executable file
169
csharp/client/result/AddressBookParsedResult.cs
Executable file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class AddressBookParsedResult:ParsedResult
|
||||
{
|
||||
public System.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 System.String Pronunciation
|
||||
{
|
||||
get
|
||||
{
|
||||
return pronunciation;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String[] PhoneNumbers
|
||||
{
|
||||
get
|
||||
{
|
||||
return phoneNumbers;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String[] Emails
|
||||
{
|
||||
get
|
||||
{
|
||||
return emails;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Note
|
||||
{
|
||||
get
|
||||
{
|
||||
return note;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String[] Addresses
|
||||
{
|
||||
get
|
||||
{
|
||||
return addresses;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Org
|
||||
{
|
||||
get
|
||||
{
|
||||
return org;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String URL
|
||||
{
|
||||
get
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> birthday formatted as yyyyMMdd (e.g. 19780917)
|
||||
/// </returns>
|
||||
public System.String Birthday
|
||||
{
|
||||
get
|
||||
{
|
||||
return birthday;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(100);
|
||||
maybeAppend(names, result);
|
||||
maybeAppend(pronunciation, result);
|
||||
maybeAppend(title, result);
|
||||
maybeAppend(org, result);
|
||||
maybeAppend(addresses, result);
|
||||
maybeAppend(phoneNumbers, result);
|
||||
maybeAppend(emails, result);
|
||||
maybeAppend(url, result);
|
||||
maybeAppend(birthday, result);
|
||||
maybeAppend(note, result);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'names '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String[] names;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'pronunciation '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String pronunciation;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'phoneNumbers '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String[] phoneNumbers;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'emails '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String[] emails;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'note '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String note;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'addresses '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String[] addresses;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'org '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String org;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'birthday '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String birthday;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'title '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String title;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'url '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String url;
|
||||
|
||||
public AddressBookParsedResult(System.String[] names, System.String pronunciation, System.String[] phoneNumbers, System.String[] emails, System.String note, System.String[] addresses, System.String org, System.String birthday, System.String title, System.String url):base(ParsedResultType.ADDRESSBOOK)
|
||||
{
|
||||
this.names = names;
|
||||
this.pronunciation = pronunciation;
|
||||
this.phoneNumbers = phoneNumbers;
|
||||
this.emails = emails;
|
||||
this.note = note;
|
||||
this.addresses = addresses;
|
||||
this.org = org;
|
||||
this.birthday = birthday;
|
||||
this.title = title;
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
}
|
98
csharp/client/result/BizcardResultParser.cs
Executable file
98
csharp/client/result/BizcardResultParser.cs
Executable file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
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 static AddressBookParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("BIZCARD:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String firstName = matchSingleDoCoMoPrefixedField("N:", rawText, true);
|
||||
System.String lastName = matchSingleDoCoMoPrefixedField("X:", rawText, true);
|
||||
System.String fullName = buildName(firstName, lastName);
|
||||
System.String title = matchSingleDoCoMoPrefixedField("T:", rawText, true);
|
||||
System.String org = matchSingleDoCoMoPrefixedField("C:", rawText, true);
|
||||
System.String[] addresses = matchDoCoMoPrefixedField("A:", rawText, true);
|
||||
System.String phoneNumber1 = matchSingleDoCoMoPrefixedField("B:", rawText, true);
|
||||
System.String phoneNumber2 = matchSingleDoCoMoPrefixedField("M:", rawText, true);
|
||||
System.String phoneNumber3 = matchSingleDoCoMoPrefixedField("F:", rawText, true);
|
||||
System.String email = matchSingleDoCoMoPrefixedField("E:", rawText, true);
|
||||
|
||||
return new AddressBookParsedResult(maybeWrap(fullName), null, buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3), maybeWrap(email), null, addresses, org, null, title, null);
|
||||
}
|
||||
|
||||
private static System.String[] buildPhoneNumbers(System.String number1, System.String number2, System.String number3)
|
||||
{
|
||||
System.Collections.ArrayList numbers = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(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;
|
||||
}
|
||||
System.String[] result = new System.String[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
result[i] = ((System.String) numbers[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static System.String buildName(System.String firstName, System.String lastName)
|
||||
{
|
||||
if (firstName == null)
|
||||
{
|
||||
return lastName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lastName == null?firstName:firstName + ' ' + lastName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
csharp/client/result/BookmarkDoCoMoResultParser.cs
Executable file
53
csharp/client/result/BookmarkDoCoMoResultParser.cs
Executable file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class BookmarkDoCoMoResultParser:AbstractDoCoMoResultParser
|
||||
{
|
||||
|
||||
private BookmarkDoCoMoResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static URIParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("MEBKM:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String title = matchSingleDoCoMoPrefixedField("TITLE:", rawText, true);
|
||||
System.String[] rawUri = matchDoCoMoPrefixedField("URL:", rawText, true);
|
||||
if (rawUri == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String uri = rawUri[0];
|
||||
if (!URIResultParser.isBasicallyValidURI(uri))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new URIParsedResult(uri, title);
|
||||
}
|
||||
}
|
||||
}
|
172
csharp/client/result/CalendarParsedResult.cs
Executable file
172
csharp/client/result/CalendarParsedResult.cs
Executable file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class CalendarParsedResult:ParsedResult
|
||||
{
|
||||
public System.String Summary
|
||||
{
|
||||
get
|
||||
{
|
||||
return summary;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary> <p>We would return the start and end date as a {@link java.util.Date} except that this code
|
||||
/// needs to work under JavaME / MIDP and there is no date parsing library available there, such
|
||||
/// as <code>java.text.SimpleDateFormat</code>.</p> See validateDate() for the return format.
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns> start time formatted as a RFC 2445 DATE or DATE-TIME.</p>
|
||||
/// </returns>
|
||||
public System.String Start
|
||||
{
|
||||
get
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
}
|
||||
/// <seealso cref="getStart(). May return null if the event has no duration.">
|
||||
/// </seealso>
|
||||
public System.String End
|
||||
{
|
||||
get
|
||||
{
|
||||
return end;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Location
|
||||
{
|
||||
get
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Attendee
|
||||
{
|
||||
get
|
||||
{
|
||||
return attendee;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(100);
|
||||
maybeAppend(summary, result);
|
||||
maybeAppend(start, result);
|
||||
maybeAppend(end, result);
|
||||
maybeAppend(location, result);
|
||||
maybeAppend(attendee, result);
|
||||
maybeAppend(title, result);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'summary '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String summary;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'start '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String start;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'end '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String end;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'location '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String location;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'attendee '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String attendee;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'title '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String title;
|
||||
|
||||
public CalendarParsedResult(System.String summary, System.String start, System.String end, System.String location, System.String attendee, System.String title):base(ParsedResultType.CALENDAR)
|
||||
{
|
||||
// Start is required, end is not
|
||||
if (start == null)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
validateDate(start);
|
||||
validateDate(end);
|
||||
this.summary = summary;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.location = location;
|
||||
this.attendee = attendee;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/// <summary> 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="date">The string to validate
|
||||
/// </param>
|
||||
private static void validateDate(System.String date)
|
||||
{
|
||||
if (date != null)
|
||||
{
|
||||
int length = date.Length;
|
||||
if (length != 8 && length != 15 && length != 16)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!System.Char.IsDigit(date[i]))
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
}
|
||||
if (length > 8)
|
||||
{
|
||||
if (date[8] != 'T')
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
for (int i = 9; i < 15; i++)
|
||||
{
|
||||
if (!System.Char.IsDigit(date[i]))
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
}
|
||||
if (length == 16 && date[15] != 'Z')
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
88
csharp/client/result/EmailAddressParsedResult.cs
Executable file
88
csharp/client/result/EmailAddressParsedResult.cs
Executable file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class EmailAddressParsedResult:ParsedResult
|
||||
{
|
||||
public System.String EmailAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Subject
|
||||
{
|
||||
get
|
||||
{
|
||||
return subject;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Body
|
||||
{
|
||||
get
|
||||
{
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String MailtoURI
|
||||
{
|
||||
get
|
||||
{
|
||||
return mailtoURI;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(30);
|
||||
maybeAppend(emailAddress, result);
|
||||
maybeAppend(subject, result);
|
||||
maybeAppend(body, result);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'emailAddress '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String emailAddress;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'subject '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String subject;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'body '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String body;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'mailtoURI '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String mailtoURI;
|
||||
|
||||
internal EmailAddressParsedResult(System.String emailAddress, System.String subject, System.String body, System.String mailtoURI):base(ParsedResultType.EMAIL_ADDRESS)
|
||||
{
|
||||
this.emailAddress = emailAddress;
|
||||
this.subject = subject;
|
||||
this.body = body;
|
||||
this.mailtoURI = mailtoURI;
|
||||
}
|
||||
}
|
||||
}
|
74
csharp/client/result/EmailAddressResultParser.cs
Executable file
74
csharp/client/result/EmailAddressResultParser.cs
Executable file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.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".
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class EmailAddressResultParser:ResultParser
|
||||
{
|
||||
|
||||
public static EmailAddressParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.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) - (0));
|
||||
}
|
||||
System.Collections.Hashtable nameValues = parseNameValuePairs(rawText);
|
||||
System.String subject = null;
|
||||
System.String body = null;
|
||||
if (nameValues != null)
|
||||
{
|
||||
if (emailAddress.Length == 0)
|
||||
{
|
||||
emailAddress = ((System.String) nameValues["to"]);
|
||||
}
|
||||
subject = ((System.String) nameValues["subject"]);
|
||||
body = ((System.String) 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
csharp/client/result/EmailDoCoMoResultParser.cs
Executable file
101
csharp/client/result/EmailDoCoMoResultParser.cs
Executable file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> Implements the "MATMSG" email message entry format.
|
||||
///
|
||||
/// Supported keys: TO, SUB, BODY
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class EmailDoCoMoResultParser:AbstractDoCoMoResultParser
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ATEXT_SYMBOLS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly char[] ATEXT_SYMBOLS = new char[]{'@', '.', '!', '#', '$', '%', '&', '\'', '*', '+', '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', '~'};
|
||||
|
||||
public static EmailAddressParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("MATMSG:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String[] rawTo = matchDoCoMoPrefixedField("TO:", rawText, true);
|
||||
if (rawTo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String to = rawTo[0];
|
||||
if (!isBasicallyValidEmailAddress(to))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String subject = matchSingleDoCoMoPrefixedField("SUB:", rawText, false);
|
||||
System.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 '@' 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(System.String email)
|
||||
{
|
||||
if (email == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool atFound = false;
|
||||
for (int i = 0; i < email.Length; i++)
|
||||
{
|
||||
char c = email[i];
|
||||
if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && !isAtextSymbol(c))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (c == '@')
|
||||
{
|
||||
if (atFound)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
atFound = true;
|
||||
}
|
||||
}
|
||||
return atFound;
|
||||
}
|
||||
|
||||
private static bool isAtextSymbol(char c)
|
||||
{
|
||||
for (int i = 0; i < ATEXT_SYMBOLS.Length; i++)
|
||||
{
|
||||
if (c == ATEXT_SYMBOLS[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
131
csharp/client/result/GeoParsedResult.cs
Executable file
131
csharp/client/result/GeoParsedResult.cs
Executable file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class GeoParsedResult:ParsedResult
|
||||
{
|
||||
public System.String GeoURI
|
||||
{
|
||||
get
|
||||
{
|
||||
return geoURI;
|
||||
}
|
||||
|
||||
}
|
||||
/// <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;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(50);
|
||||
result.Append(latitude);
|
||||
result.Append(", ");
|
||||
result.Append(longitude);
|
||||
if (altitude > 0.0f)
|
||||
{
|
||||
result.Append(", ");
|
||||
result.Append(altitude);
|
||||
result.Append('m');
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
/// <returns> a URI link to Google Maps which display the point on the Earth described
|
||||
/// by this instance, and sets the zoom level in a way that roughly reflects the
|
||||
/// altitude, if specified
|
||||
/// </returns>
|
||||
/*
|
||||
public String getGoogleMapsURI() {
|
||||
StringBuffer result = new StringBuffer(50);
|
||||
result.append("http://maps.google.com/?ll=");
|
||||
result.append(latitude);
|
||||
result.append(',');
|
||||
result.append(longitude);
|
||||
if (altitude > 0.0f) {
|
||||
// Map altitude to zoom level, cleverly. Roughly, zoom level 19 is like a
|
||||
// view from 1000ft, 18 is like 2000ft, 17 like 4000ft, and so on.
|
||||
double altitudeInFeet = altitude * 3.28;
|
||||
int altitudeInKFeet = (int) (altitudeInFeet / 1000.0);
|
||||
// No Math.log() available here, so compute log base 2 the old fashioned way
|
||||
// Here logBaseTwo will take on a value between 0 and 18 actually
|
||||
int logBaseTwo = 0;
|
||||
while (altitudeInKFeet > 1 && logBaseTwo < 18) {
|
||||
altitudeInKFeet >>= 1;
|
||||
logBaseTwo++;
|
||||
}
|
||||
int zoom = 19 - logBaseTwo;
|
||||
result.append("&z=");
|
||||
result.append(zoom);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'geoURI '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String geoURI;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'latitude '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private double latitude;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'longitude '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private double longitude;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'altitude '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private double altitude;
|
||||
|
||||
internal GeoParsedResult(System.String geoURI, double latitude, double longitude, double altitude):base(ParsedResultType.GEO)
|
||||
{
|
||||
this.geoURI = geoURI;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
this.altitude = altitude;
|
||||
}
|
||||
}
|
||||
}
|
78
csharp/client/result/GeoResultParser.cs
Executable file
78
csharp/client/result/GeoResultParser.cs
Executable file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.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>.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class GeoResultParser:ResultParser
|
||||
{
|
||||
|
||||
private GeoResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static GeoParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || (!rawText.StartsWith("geo:") && !rawText.StartsWith("GEO:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Drop geo, query portion
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int queryStart = rawText.IndexOf('?', 4);
|
||||
System.String geoURIWithoutQuery = queryStart < 0?rawText.Substring(4):rawText.Substring(4, (queryStart) - (4));
|
||||
int latitudeEnd = geoURIWithoutQuery.IndexOf(',');
|
||||
if (latitudeEnd < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int longitudeEnd = geoURIWithoutQuery.IndexOf(',', latitudeEnd + 1);
|
||||
double latitude, longitude, altitude;
|
||||
try
|
||||
{
|
||||
latitude = System.Double.Parse(geoURIWithoutQuery.Substring(0, (latitudeEnd) - (0)));
|
||||
if (longitudeEnd < 0)
|
||||
{
|
||||
longitude = System.Double.Parse(geoURIWithoutQuery.Substring(latitudeEnd + 1));
|
||||
altitude = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
longitude = System.Double.Parse(geoURIWithoutQuery.Substring(latitudeEnd + 1, (longitudeEnd) - (latitudeEnd + 1)));
|
||||
altitude = System.Double.Parse(geoURIWithoutQuery.Substring(longitudeEnd + 1));
|
||||
}
|
||||
}
|
||||
catch (System.FormatException nfe)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new GeoParsedResult(rawText.StartsWith("GEO:")?"geo:" + rawText.Substring(4):rawText, latitude, longitude, altitude);
|
||||
}
|
||||
}
|
||||
}
|
51
csharp/client/result/ISBNParsedResult.cs
Executable file
51
csharp/client/result/ISBNParsedResult.cs
Executable file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> jbreiden@google.com (Jeff Breidenbach)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ISBNParsedResult:ParsedResult
|
||||
{
|
||||
public System.String ISBN
|
||||
{
|
||||
get
|
||||
{
|
||||
return isbn;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return isbn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'isbn '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String isbn;
|
||||
|
||||
internal ISBNParsedResult(System.String isbn):base(ParsedResultType.ISBN)
|
||||
{
|
||||
this.isbn = isbn;
|
||||
}
|
||||
}
|
||||
}
|
63
csharp/client/result/ISBNResultParser.cs
Executable file
63
csharp/client/result/ISBNResultParser.cs
Executable file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> Parses strings of digits that represent a ISBN.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> jbreiden@google.com (Jeff Breidenbach)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public class ISBNResultParser:ResultParser
|
||||
{
|
||||
|
||||
private ISBNResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
// ISBN-13 For Dummies
|
||||
// http://www.bisg.org/isbn-13/for.dummies.html
|
||||
public static ISBNParsedResult parse(Result result)
|
||||
{
|
||||
BarcodeFormat format = result.BarcodeFormat;
|
||||
if (!BarcodeFormat.EAN_13.Equals(format))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int length = rawText.Length;
|
||||
if (length != 13)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!rawText.StartsWith("978") && !rawText.StartsWith("979"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ISBNParsedResult(rawText);
|
||||
}
|
||||
}
|
||||
}
|
90
csharp/client/result/ParsedResult.cs
Executable file
90
csharp/client/result/ParsedResult.cs
Executable file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
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. {@link ResultParser#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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public abstract class ParsedResult
|
||||
{
|
||||
virtual public ParsedResultType Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
public abstract System.String DisplayResult{get;}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'type '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ParsedResultType type;
|
||||
|
||||
protected internal ParsedResult(ParsedResultType type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
return DisplayResult;
|
||||
}
|
||||
|
||||
public static void maybeAppend(System.String value_Renamed, System.Text.StringBuilder result)
|
||||
{
|
||||
if (value_Renamed != null && value_Renamed.Length > 0)
|
||||
{
|
||||
// Don't add a newline before the first value
|
||||
if (result.Length > 0)
|
||||
{
|
||||
result.Append('\n');
|
||||
}
|
||||
result.Append(value_Renamed);
|
||||
}
|
||||
}
|
||||
|
||||
public static void maybeAppend(System.String[] value_Renamed, System.Text.StringBuilder result)
|
||||
{
|
||||
if (value_Renamed != null)
|
||||
{
|
||||
for (int i = 0; i < value_Renamed.Length; i++)
|
||||
{
|
||||
if (value_Renamed[i] != null && value_Renamed[i].Length > 0)
|
||||
{
|
||||
if (result.Length > 0)
|
||||
{
|
||||
result.Append('\n');
|
||||
}
|
||||
result.Append(value_Renamed[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
csharp/client/result/ParsedResultType.cs
Executable file
72
csharp/client/result/ParsedResultType.cs
Executable file
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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;
|
||||
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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ParsedResultType
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ADDRESSBOOK '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType ADDRESSBOOK = new ParsedResultType("ADDRESSBOOK");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'EMAIL_ADDRESS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType EMAIL_ADDRESS = new ParsedResultType("EMAIL_ADDRESS");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'PRODUCT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType PRODUCT = new ParsedResultType("PRODUCT");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'URI '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType URI = new ParsedResultType("URI");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'TEXT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType TEXT = new ParsedResultType("TEXT");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ANDROID_INTENT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType ANDROID_INTENT = new ParsedResultType("ANDROID_INTENT");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'GEO '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType GEO = new ParsedResultType("GEO");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'TEL '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType TEL = new ParsedResultType("TEL");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'SMS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType SMS = new ParsedResultType("SMS");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'CALENDAR '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType CALENDAR = new ParsedResultType("CALENDAR");
|
||||
// "optional" types
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'NDEF_SMART_POSTER '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType NDEF_SMART_POSTER = new ParsedResultType("NDEF_SMART_POSTER");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'MOBILETAG_RICH_WEB '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType MOBILETAG_RICH_WEB = new ParsedResultType("MOBILETAG_RICH_WEB");
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ISBN '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly ParsedResultType ISBN = new ParsedResultType("ISBN");
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'name '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String name;
|
||||
|
||||
private ParsedResultType(System.String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
66
csharp/client/result/ProductParsedResult.cs
Executable file
66
csharp/client/result/ProductParsedResult.cs
Executable file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ProductParsedResult:ParsedResult
|
||||
{
|
||||
public System.String ProductID
|
||||
{
|
||||
get
|
||||
{
|
||||
return productID;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String NormalizedProductID
|
||||
{
|
||||
get
|
||||
{
|
||||
return normalizedProductID;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return productID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'productID '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String productID;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'normalizedProductID '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String normalizedProductID;
|
||||
|
||||
internal ProductParsedResult(System.String productID):this(productID, productID)
|
||||
{
|
||||
}
|
||||
|
||||
internal ProductParsedResult(System.String productID, System.String normalizedProductID):base(ParsedResultType.PRODUCT)
|
||||
{
|
||||
this.productID = productID;
|
||||
this.normalizedProductID = normalizedProductID;
|
||||
}
|
||||
}
|
||||
}
|
77
csharp/client/result/ProductResultParser.cs
Executable file
77
csharp/client/result/ProductResultParser.cs
Executable file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using Result = com.google.zxing.Result;
|
||||
using UPCEReader = com.google.zxing.oned.UPCEReader;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> Parses strings of digits that represent a UPC code.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class ProductResultParser:ResultParser
|
||||
{
|
||||
|
||||
private ProductResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
// Treat all UPC and EAN variants as UPCs, in the sense that they are all product barcodes.
|
||||
public static ProductParsedResult parse(Result result)
|
||||
{
|
||||
BarcodeFormat format = result.BarcodeFormat;
|
||||
if (!(BarcodeFormat.UPC_A.Equals(format) || BarcodeFormat.UPC_E.Equals(format) || BarcodeFormat.EAN_8.Equals(format) || BarcodeFormat.EAN_13.Equals(format)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Really neither of these should happen:
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
System.String normalizedProductID;
|
||||
// Expand UPC-E for purposes of searching
|
||||
if (BarcodeFormat.UPC_E.Equals(format))
|
||||
{
|
||||
normalizedProductID = UPCEReader.convertUPCEtoUPCA(rawText);
|
||||
}
|
||||
else
|
||||
{
|
||||
normalizedProductID = rawText;
|
||||
}
|
||||
|
||||
return new ProductParsedResult(rawText, normalizedProductID);
|
||||
}
|
||||
}
|
||||
}
|
415
csharp/client/result/ResultParser.cs
Executable file
415
csharp/client/result/ResultParser.cs
Executable file
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
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. {@link #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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public abstract class ResultParser
|
||||
{
|
||||
|
||||
public static ParsedResult parseResult(Result theResult)
|
||||
{
|
||||
// This is a bit messy, but given limited options in MIDP / CLDC, this may well be the simplest
|
||||
// way to go about this. For example, we have no reflection available, really.
|
||||
// Order is important here.
|
||||
ParsedResult result;
|
||||
if ((result = BookmarkDoCoMoResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = AddressBookDoCoMoResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = EmailDoCoMoResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = AddressBookAUResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = VCardResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = BizcardResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = VEventResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = EmailAddressResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = TelResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = SMSMMSResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = GeoResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = URLTOResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = URIResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else if ((result = ISBNResultParser.parse(theResult)) != null)
|
||||
{
|
||||
// We depend on ISBN parsing coming before UPC, as it is a subset.
|
||||
return result;
|
||||
}
|
||||
else if ((result = ProductResultParser.parse(theResult)) != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return new TextParsedResult(theResult.Text, null);
|
||||
}
|
||||
|
||||
protected internal static void maybeAppend(System.String value_Renamed, System.Text.StringBuilder result)
|
||||
{
|
||||
if (value_Renamed != null)
|
||||
{
|
||||
result.Append('\n');
|
||||
result.Append(value_Renamed);
|
||||
}
|
||||
}
|
||||
|
||||
protected internal static void maybeAppend(System.String[] value_Renamed, System.Text.StringBuilder result)
|
||||
{
|
||||
if (value_Renamed != null)
|
||||
{
|
||||
for (int i = 0; i < value_Renamed.Length; i++)
|
||||
{
|
||||
result.Append('\n');
|
||||
result.Append(value_Renamed[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected internal static System.String[] maybeWrap(System.String value_Renamed)
|
||||
{
|
||||
return value_Renamed == null?null:new System.String[]{value_Renamed};
|
||||
}
|
||||
|
||||
protected internal static System.String unescapeBackslash(System.String escaped)
|
||||
{
|
||||
if (escaped != null)
|
||||
{
|
||||
int backslash = escaped.IndexOf('\\');
|
||||
if (backslash >= 0)
|
||||
{
|
||||
int max = escaped.Length;
|
||||
System.Text.StringBuilder unescaped = new System.Text.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();
|
||||
}
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
||||
private static System.String urlDecode(System.String escaped)
|
||||
{
|
||||
|
||||
// No we can't use java.net.URLDecoder here. JavaME doesn't have it.
|
||||
if (escaped == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
char[] escapedArray = escaped.ToCharArray();
|
||||
|
||||
int first = findFirstEscape(escapedArray);
|
||||
if (first < 0)
|
||||
{
|
||||
return escaped;
|
||||
}
|
||||
|
||||
int max = escapedArray.Length;
|
||||
// final length is at most 2 less than original due to at least 1 unescaping
|
||||
System.Text.StringBuilder unescaped = new System.Text.StringBuilder(max - 2);
|
||||
// Can append everything up to first escape character
|
||||
unescaped.Append(escapedArray, 0, first);
|
||||
|
||||
for (int i = first; i < max; i++)
|
||||
{
|
||||
char c = escapedArray[i];
|
||||
if (c == '+')
|
||||
{
|
||||
// + is translated directly into a space
|
||||
unescaped.Append(' ');
|
||||
}
|
||||
else if (c == '%')
|
||||
{
|
||||
// Are there even two more chars? if not we will just copy the escaped sequence and be done
|
||||
if (i >= max - 2)
|
||||
{
|
||||
unescaped.Append('%'); // append that % and move on
|
||||
}
|
||||
else
|
||||
{
|
||||
int firstDigitValue = parseHexDigit(escapedArray[++i]);
|
||||
int secondDigitValue = parseHexDigit(escapedArray[++i]);
|
||||
if (firstDigitValue < 0 || secondDigitValue < 0)
|
||||
{
|
||||
// bad digit, just move on
|
||||
unescaped.Append('%');
|
||||
unescaped.Append(escapedArray[i - 1]);
|
||||
unescaped.Append(escapedArray[i]);
|
||||
}
|
||||
unescaped.Append((char) ((firstDigitValue << 4) + secondDigitValue));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unescaped.Append(c);
|
||||
}
|
||||
}
|
||||
return unescaped.ToString();
|
||||
}
|
||||
|
||||
private static int findFirstEscape(char[] escapedArray)
|
||||
{
|
||||
int max = escapedArray.Length;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
char c = escapedArray[i];
|
||||
if (c == '+' || c == '%')
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return - 1;
|
||||
}
|
||||
|
||||
private static int parseHexDigit(char c)
|
||||
{
|
||||
if (c >= 'a')
|
||||
{
|
||||
if (c <= 'f')
|
||||
{
|
||||
return 10 + (c - 'a');
|
||||
}
|
||||
}
|
||||
else if (c >= 'A')
|
||||
{
|
||||
if (c <= 'F')
|
||||
{
|
||||
return 10 + (c - 'A');
|
||||
}
|
||||
}
|
||||
else if (c >= '0')
|
||||
{
|
||||
if (c <= '9')
|
||||
{
|
||||
return c - '0';
|
||||
}
|
||||
}
|
||||
return - 1;
|
||||
}
|
||||
|
||||
protected internal static bool isStringOfDigits(System.String value_Renamed, int length)
|
||||
{
|
||||
if (value_Renamed == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int stringLength = value_Renamed.Length;
|
||||
if (length != stringLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
char c = value_Renamed[i];
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected internal static bool isSubstringOfDigits(System.String value_Renamed, int offset, int length)
|
||||
{
|
||||
if (value_Renamed == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int stringLength = value_Renamed.Length;
|
||||
int max = offset + length;
|
||||
if (stringLength < max)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = offset; i < max; i++)
|
||||
{
|
||||
char c = value_Renamed[i];
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static System.Collections.Hashtable parseNameValuePairs(System.String uri)
|
||||
{
|
||||
int paramStart = uri.IndexOf('?');
|
||||
if (paramStart < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.Collections.Hashtable result = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(3));
|
||||
paramStart++;
|
||||
int paramEnd;
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
while ((paramEnd = uri.IndexOf('&', paramStart)) >= 0)
|
||||
{
|
||||
appendKeyValue(uri, paramStart, paramEnd, result);
|
||||
paramStart = paramEnd + 1;
|
||||
}
|
||||
appendKeyValue(uri, paramStart, uri.Length, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void appendKeyValue(System.String uri, int paramStart, int paramEnd, System.Collections.Hashtable result)
|
||||
{
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int separator = uri.IndexOf('=', paramStart);
|
||||
if (separator >= 0)
|
||||
{
|
||||
// key = value
|
||||
System.String key = uri.Substring(paramStart, (separator) - (paramStart));
|
||||
System.String value_Renamed = uri.Substring(separator + 1, (paramEnd) - (separator + 1));
|
||||
value_Renamed = urlDecode(value_Renamed);
|
||||
result[key] = value_Renamed;
|
||||
}
|
||||
// Can't put key, null into a hashtable
|
||||
}
|
||||
|
||||
internal static System.String[] matchPrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)
|
||||
{
|
||||
System.Collections.ArrayList matches = null;
|
||||
int i = 0;
|
||||
int max = rawText.Length;
|
||||
while (i < max)
|
||||
{
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
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 done = false;
|
||||
while (!done)
|
||||
{
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
i = rawText.IndexOf((System.Char) endChar, i);
|
||||
if (i < 0)
|
||||
{
|
||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||
i = rawText.Length;
|
||||
done = true;
|
||||
}
|
||||
else if (rawText[i - 1] == '\\')
|
||||
{
|
||||
// semicolon was escaped so continue
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// found a match
|
||||
if (matches == null)
|
||||
{
|
||||
matches = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(3)); // lazy init
|
||||
}
|
||||
System.String element = unescapeBackslash(rawText.Substring(start, (i) - (start)));
|
||||
if (trim)
|
||||
{
|
||||
element = element.Trim();
|
||||
}
|
||||
matches.Add(element);
|
||||
i++;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matches == null || (matches.Count == 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return toStringArray(matches);
|
||||
}
|
||||
|
||||
internal static System.String matchSinglePrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)
|
||||
{
|
||||
System.String[] matches = matchPrefixedField(prefix, rawText, endChar, trim);
|
||||
return matches == null?null:matches[0];
|
||||
}
|
||||
|
||||
internal static System.String[] toStringArray(System.Collections.ArrayList strings)
|
||||
{
|
||||
int size = strings.Count;
|
||||
System.String[] result = new System.String[size];
|
||||
for (int j = 0; j < size; j++)
|
||||
{
|
||||
result[j] = ((System.String) strings[j]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
123
csharp/client/result/SMSMMSResultParser.cs
Executable file
123
csharp/client/result/SMSMMSResultParser.cs
Executable file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> <p>Parses an "sms:" URI result, which specifies a number to SMS and optional
|
||||
/// "via" number. See <a href="http://gbiv.com/protocols/uri/drafts/draft-antti-gsm-sms-url-04.txt">
|
||||
/// the IETF draft</a> on this.</p>
|
||||
///
|
||||
/// <p>This actually also parses URIs starting with "mms:", "smsto:", "mmsto:", "SMSTO:", and
|
||||
/// "MMSTO:", and treats them all the same way, and effectively converts them to an "sms:" URI
|
||||
/// for purposes of forwarding to the platform.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class SMSMMSResultParser:ResultParser
|
||||
{
|
||||
|
||||
private SMSMMSResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static SMSParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int prefixLength;
|
||||
if (rawText.StartsWith("sms:") || rawText.StartsWith("SMS:") || rawText.StartsWith("mms:") || rawText.StartsWith("MMS:"))
|
||||
{
|
||||
prefixLength = 4;
|
||||
}
|
||||
else if (rawText.StartsWith("smsto:") || rawText.StartsWith("SMSTO:") || rawText.StartsWith("mmsto:") || rawText.StartsWith("MMSTO:"))
|
||||
{
|
||||
prefixLength = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check up front if this is a URI syntax string with query arguments
|
||||
System.Collections.Hashtable nameValuePairs = parseNameValuePairs(rawText);
|
||||
System.String subject = null;
|
||||
System.String body = null;
|
||||
bool querySyntax = false;
|
||||
if (nameValuePairs != null && !(nameValuePairs.Count == 0))
|
||||
{
|
||||
subject = ((System.String) nameValuePairs["subject"]);
|
||||
body = ((System.String) nameValuePairs["body"]);
|
||||
querySyntax = true;
|
||||
}
|
||||
|
||||
// Drop sms, query portion
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int queryStart = rawText.IndexOf('?', prefixLength);
|
||||
System.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(prefixLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
smsURIWithoutQuery = rawText.Substring(prefixLength, (queryStart) - (prefixLength));
|
||||
}
|
||||
int numberEnd = smsURIWithoutQuery.IndexOf(';');
|
||||
System.String number;
|
||||
System.String via;
|
||||
if (numberEnd < 0)
|
||||
{
|
||||
number = smsURIWithoutQuery;
|
||||
via = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = smsURIWithoutQuery.Substring(0, (numberEnd) - (0));
|
||||
System.String maybeVia = smsURIWithoutQuery.Substring(numberEnd + 1);
|
||||
if (maybeVia.StartsWith("via="))
|
||||
{
|
||||
via = maybeVia.Substring(4);
|
||||
}
|
||||
else
|
||||
{
|
||||
via = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Thanks to dominik.wild for suggesting this enhancement to support
|
||||
// smsto:number:body URIs
|
||||
if (body == null)
|
||||
{
|
||||
int bodyStart = number.IndexOf(':');
|
||||
if (bodyStart >= 0)
|
||||
{
|
||||
body = number.Substring(bodyStart + 1);
|
||||
number = number.Substring(0, (bodyStart) - (0));
|
||||
}
|
||||
}
|
||||
return new SMSParsedResult("sms:" + number, number, via, subject, body, null);
|
||||
}
|
||||
}
|
||||
}
|
112
csharp/client/result/SMSParsedResult.cs
Executable file
112
csharp/client/result/SMSParsedResult.cs
Executable file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class SMSParsedResult:ParsedResult
|
||||
{
|
||||
public System.String SMSURI
|
||||
{
|
||||
get
|
||||
{
|
||||
return smsURI;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Number
|
||||
{
|
||||
get
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Via
|
||||
{
|
||||
get
|
||||
{
|
||||
return via;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Subject
|
||||
{
|
||||
get
|
||||
{
|
||||
return subject;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Body
|
||||
{
|
||||
get
|
||||
{
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(100);
|
||||
maybeAppend(number, result);
|
||||
maybeAppend(via, result);
|
||||
maybeAppend(subject, result);
|
||||
maybeAppend(body, result);
|
||||
maybeAppend(title, result);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'smsURI '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String smsURI;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'number '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String number;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'via '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String via;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'subject '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String subject;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'body '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String body;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'title '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String title;
|
||||
|
||||
public SMSParsedResult(System.String smsURI, System.String number, System.String via, System.String subject, System.String body, System.String title):base(ParsedResultType.SMS)
|
||||
{
|
||||
this.smsURI = smsURI;
|
||||
this.number = number;
|
||||
this.via = via;
|
||||
this.subject = subject;
|
||||
this.body = body;
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
}
|
76
csharp/client/result/TelParsedResult.cs
Executable file
76
csharp/client/result/TelParsedResult.cs
Executable file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class TelParsedResult:ParsedResult
|
||||
{
|
||||
public System.String Number
|
||||
{
|
||||
get
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String TelURI
|
||||
{
|
||||
get
|
||||
{
|
||||
return telURI;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(20);
|
||||
maybeAppend(number, result);
|
||||
maybeAppend(title, result);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'number '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String number;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'telURI '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String telURI;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'title '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String title;
|
||||
|
||||
public TelParsedResult(System.String number, System.String telURI, System.String title):base(ParsedResultType.TEL)
|
||||
{
|
||||
this.number = number;
|
||||
this.telURI = telURI;
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
}
|
51
csharp/client/result/TelResultParser.cs
Executable file
51
csharp/client/result/TelResultParser.cs
Executable file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> Parses a "tel:" URI result, which specifies a phone number.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class TelResultParser:ResultParser
|
||||
{
|
||||
|
||||
private TelResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static TelParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || (!rawText.StartsWith("tel:") && !rawText.StartsWith("TEL:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Normalize "TEL:" to "tel:"
|
||||
System.String telURI = rawText.StartsWith("TEL:")?"tel:" + rawText.Substring(4):rawText;
|
||||
// Drop tel, query portion
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int queryStart = rawText.IndexOf('?', 4);
|
||||
System.String number = queryStart < 0?rawText.Substring(4):rawText.Substring(4, (queryStart) - (4));
|
||||
return new TelParsedResult(number, telURI, null);
|
||||
}
|
||||
}
|
||||
}
|
66
csharp/client/result/TextParsedResult.cs
Executable file
66
csharp/client/result/TextParsedResult.cs
Executable file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> A simple result type encapsulating a string that has no further
|
||||
/// interpretation.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class TextParsedResult:ParsedResult
|
||||
{
|
||||
public System.String Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Language
|
||||
{
|
||||
get
|
||||
{
|
||||
return language;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'text '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String text;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'language '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String language;
|
||||
|
||||
public TextParsedResult(System.String text, System.String language):base(ParsedResultType.TEXT)
|
||||
{
|
||||
this.text = text;
|
||||
this.language = language;
|
||||
}
|
||||
}
|
||||
}
|
148
csharp/client/result/URIParsedResult.cs
Executable file
148
csharp/client/result/URIParsedResult.cs
Executable file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class URIParsedResult:ParsedResult
|
||||
{
|
||||
public System.String URI
|
||||
{
|
||||
get
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
}
|
||||
public System.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 containsUser();
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(30);
|
||||
maybeAppend(title, result);
|
||||
maybeAppend(uri, result);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'uri '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String uri;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'title '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String title;
|
||||
|
||||
public URIParsedResult(System.String uri, System.String title):base(ParsedResultType.URI)
|
||||
{
|
||||
this.uri = massageURI(uri);
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
private bool containsUser()
|
||||
{
|
||||
// This method is likely not 100% RFC compliant yet
|
||||
int hostStart = uri.IndexOf(':'); // we should always have scheme at this point
|
||||
hostStart++;
|
||||
// Skip slashes preceding host
|
||||
int uriLength = uri.Length;
|
||||
while (hostStart < uriLength && uri[hostStart] == '/')
|
||||
{
|
||||
hostStart++;
|
||||
}
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int hostEnd = uri.IndexOf('/', hostStart);
|
||||
if (hostEnd < 0)
|
||||
{
|
||||
hostEnd = uriLength;
|
||||
}
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int at = uri.IndexOf('@', hostStart);
|
||||
return at >= hostStart && at < hostEnd;
|
||||
}
|
||||
|
||||
/// <summary> Transforms a string that represents a URI into something more proper, by adding or canonicalizing
|
||||
/// the protocol.
|
||||
/// </summary>
|
||||
private static System.String massageURI(System.String uri)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lowercase protocol to avoid problems
|
||||
uri = uri.Substring(0, (protocolEnd) - (0)).ToLower() + uri.Substring(protocolEnd);
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
private static bool isColonFollowedByPortNumber(System.String uri, int protocolEnd)
|
||||
{
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
106
csharp/client/result/URIResultParser.cs
Executable file
106
csharp/client/result/URIResultParser.cs
Executable file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> Tries to parse results that are a URI of some kind.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class URIResultParser:ResultParser
|
||||
{
|
||||
|
||||
private URIResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static URIParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
// We specifically handle the odd "URL" scheme here for simplicity
|
||||
if (rawText != null && rawText.StartsWith("URL:"))
|
||||
{
|
||||
rawText = rawText.Substring(4);
|
||||
}
|
||||
if (!isBasicallyValidURI(rawText))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new URIParsedResult(rawText, null);
|
||||
}
|
||||
|
||||
/// <summary> Determines whether a string is not obviously not a URI. This implements crude checks; this class does not
|
||||
/// intend to strictly check URIs as its only function is to represent what is in a barcode, but, it does
|
||||
/// need to know when a string is obviously not a URI.
|
||||
/// </summary>
|
||||
internal static bool isBasicallyValidURI(System.String uri)
|
||||
{
|
||||
if (uri == null || uri.IndexOf(' ') >= 0 || uri.IndexOf('\n') >= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Look for period in a domain but followed by at least a two-char TLD
|
||||
// Forget strings that don't have a valid-looking protocol
|
||||
int period = uri.IndexOf('.');
|
||||
if (period >= uri.Length - 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int colon = uri.IndexOf(':');
|
||||
if (period < 0 && colon < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (colon >= 0)
|
||||
{
|
||||
if (period < 0 || period > colon)
|
||||
{
|
||||
// colon ends the protocol
|
||||
for (int i = 0; i < colon; i++)
|
||||
{
|
||||
char c = uri[i];
|
||||
if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// colon starts the port; crudely look for at least two numbers
|
||||
if (colon >= uri.Length - 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = colon + 1; i < colon + 3; i++)
|
||||
{
|
||||
char c = uri[i];
|
||||
if (c < '0' || c > '9')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
55
csharp/client/result/URLTOResultParser.cs
Executable file
55
csharp/client/result/URLTOResultParser.cs
Executable file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.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?
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class URLTOResultParser
|
||||
{
|
||||
|
||||
private URLTOResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static URIParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || (!rawText.StartsWith("urlto:") && !rawText.StartsWith("URLTO:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int titleEnd = rawText.IndexOf(':', 6);
|
||||
if (titleEnd < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String title = titleEnd <= 6?null:rawText.Substring(6, (titleEnd) - (6));
|
||||
System.String uri = rawText.Substring(titleEnd + 1);
|
||||
return new URIParsedResult(uri, title);
|
||||
}
|
||||
}
|
||||
}
|
230
csharp/client/result/VCardResultParser.cs
Executable file
230
csharp/client/result/VCardResultParser.cs
Executable file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class VCardResultParser:ResultParser
|
||||
{
|
||||
|
||||
private VCardResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static AddressBookParsedResult 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.
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("BEGIN:VCARD"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String[] names = matchVCardPrefixedField("FN", rawText, true);
|
||||
if (names == null)
|
||||
{
|
||||
// If no display names found, look for regular name fields and format them
|
||||
names = matchVCardPrefixedField("N", rawText, true);
|
||||
formatNames(names);
|
||||
}
|
||||
System.String[] phoneNumbers = matchVCardPrefixedField("TEL", rawText, true);
|
||||
System.String[] emails = matchVCardPrefixedField("EMAIL", rawText, true);
|
||||
System.String note = matchSingleVCardPrefixedField("NOTE", rawText, false);
|
||||
System.String[] addresses = matchVCardPrefixedField("ADR", rawText, true);
|
||||
if (addresses != null)
|
||||
{
|
||||
for (int i = 0; i < addresses.Length; i++)
|
||||
{
|
||||
addresses[i] = formatAddress(addresses[i]);
|
||||
}
|
||||
}
|
||||
System.String org = matchSingleVCardPrefixedField("ORG", rawText, true);
|
||||
System.String birthday = matchSingleVCardPrefixedField("BDAY", rawText, true);
|
||||
if (!isLikeVCardDate(birthday))
|
||||
{
|
||||
birthday = null;
|
||||
}
|
||||
System.String title = matchSingleVCardPrefixedField("TITLE", rawText, true);
|
||||
System.String url = matchSingleVCardPrefixedField("URL", rawText, true);
|
||||
return new AddressBookParsedResult(names, null, phoneNumbers, emails, note, addresses, org, birthday, title, url);
|
||||
}
|
||||
|
||||
private static System.String[] matchVCardPrefixedField(System.String prefix, System.String rawText, bool trim)
|
||||
{
|
||||
System.Collections.ArrayList matches = null;
|
||||
int i = 0;
|
||||
int max = rawText.Length;
|
||||
while (i < max)
|
||||
{
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
i = rawText.IndexOf(prefix, i);
|
||||
if (i < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (i > 0 && rawText[i - 1] != '\n')
|
||||
{
|
||||
// then this didn't start a new token, we matched in the middle of something
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i += prefix.Length; // Skip past this prefix we found to start
|
||||
if (rawText[i] != ':' && rawText[i] != ';')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
while (rawText[i] != ':')
|
||||
{
|
||||
// Skip until a colon
|
||||
i++;
|
||||
}
|
||||
i++; // skip colon
|
||||
int start = i; // Found the start of a match here
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
i = rawText.IndexOf('\n', i); // Really, ends in \r\n
|
||||
if (i < 0)
|
||||
{
|
||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||
i = max;
|
||||
}
|
||||
else if (i > start)
|
||||
{
|
||||
// found a match
|
||||
if (matches == null)
|
||||
{
|
||||
matches = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(3)); // lazy init
|
||||
}
|
||||
System.String element = rawText.Substring(start, (i) - (start));
|
||||
if (trim)
|
||||
{
|
||||
element = element.Trim();
|
||||
}
|
||||
matches.Add(element);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (matches == null || (matches.Count == 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return toStringArray(matches);
|
||||
}
|
||||
|
||||
internal static System.String matchSingleVCardPrefixedField(System.String prefix, System.String rawText, bool trim)
|
||||
{
|
||||
System.String[] values = matchVCardPrefixedField(prefix, rawText, trim);
|
||||
return values == null?null:values[0];
|
||||
}
|
||||
|
||||
private static bool isLikeVCardDate(System.String value_Renamed)
|
||||
{
|
||||
if (value_Renamed == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Not really sure this is true but matches practice
|
||||
// Mach YYYYMMDD
|
||||
if (isStringOfDigits(value_Renamed, 8))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// or YYYY-MM-DD
|
||||
return value_Renamed.Length == 10 && value_Renamed[4] == '-' && value_Renamed[7] == '-' && isSubstringOfDigits(value_Renamed, 0, 4) && isSubstringOfDigits(value_Renamed, 5, 2) && isSubstringOfDigits(value_Renamed, 8, 2);
|
||||
}
|
||||
|
||||
private static System.String formatAddress(System.String address)
|
||||
{
|
||||
if (address == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int length = address.Length;
|
||||
System.Text.StringBuilder newAddress = new System.Text.StringBuilder(length);
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
char c = address[j];
|
||||
if (c == ';')
|
||||
{
|
||||
newAddress.Append(' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
newAddress.Append(c);
|
||||
}
|
||||
}
|
||||
return newAddress.ToString().Trim();
|
||||
}
|
||||
|
||||
/// <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(System.String[] names)
|
||||
{
|
||||
if (names != null)
|
||||
{
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
System.String name = names[i];
|
||||
System.String[] components = new System.String[5];
|
||||
int start = 0;
|
||||
int end;
|
||||
int componentIndex = 0;
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
while ((end = name.IndexOf(';', start)) > 0)
|
||||
{
|
||||
components[componentIndex] = name.Substring(start, (end) - (start));
|
||||
componentIndex++;
|
||||
start = end + 1;
|
||||
}
|
||||
components[componentIndex] = name.Substring(start);
|
||||
System.Text.StringBuilder newName = new System.Text.StringBuilder(100);
|
||||
maybeAppendComponent(components, 3, newName);
|
||||
maybeAppendComponent(components, 1, newName);
|
||||
maybeAppendComponent(components, 2, newName);
|
||||
maybeAppendComponent(components, 0, newName);
|
||||
maybeAppendComponent(components, 4, newName);
|
||||
names[i] = newName.ToString().Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void maybeAppendComponent(System.String[] components, int i, System.Text.StringBuilder newName)
|
||||
{
|
||||
if (components[i] != null)
|
||||
{
|
||||
newName.Append(' ');
|
||||
newName.Append(components[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
csharp/client/result/VEventResultParser.cs
Executable file
67
csharp/client/result/VEventResultParser.cs
Executable file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result
|
||||
{
|
||||
|
||||
/// <summary> Partially implements the iCalendar format's "VEVENT" format for specifying a
|
||||
/// calendar event. See RFC 2445. This supports SUMMARY, DTSTART and DTEND fields.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class VEventResultParser:ResultParser
|
||||
{
|
||||
|
||||
private VEventResultParser()
|
||||
{
|
||||
}
|
||||
|
||||
public static CalendarParsedResult parse(Result result)
|
||||
{
|
||||
System.String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int vEventStart = rawText.IndexOf("BEGIN:VEVENT");
|
||||
if (vEventStart < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int vEventEnd = rawText.IndexOf("END:VEVENT");
|
||||
if (vEventEnd < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
System.String summary = VCardResultParser.matchSingleVCardPrefixedField("SUMMARY", rawText, true);
|
||||
System.String start = VCardResultParser.matchSingleVCardPrefixedField("DTSTART", rawText, true);
|
||||
System.String end = VCardResultParser.matchSingleVCardPrefixedField("DTEND", rawText, true);
|
||||
try
|
||||
{
|
||||
return new CalendarParsedResult(summary, start, end, null, null, null);
|
||||
}
|
||||
catch (System.ArgumentException iae)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
54
csharp/client/result/optional/AbstractNDEFResultParser.cs
Executable file
54
csharp/client/result/optional/AbstractNDEFResultParser.cs
Executable file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 ResultParser = com.google.zxing.client.result.ResultParser;
|
||||
namespace com.google.zxing.client.result.optional
|
||||
{
|
||||
|
||||
/// <summary> <p>Superclass for classes encapsulating results in the NDEF format.
|
||||
/// See <a href="http://www.nfc-forum.org/specs/">http://www.nfc-forum.org/specs/</a>.</p>
|
||||
///
|
||||
/// <p>This code supports a limited subset of NDEF messages, ones that are plausibly
|
||||
/// useful in 2D barcode formats. This generally includes 1-record messages, no chunking,
|
||||
/// "short record" syntax, no ID field.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
abstract class AbstractNDEFResultParser:ResultParser
|
||||
{
|
||||
|
||||
internal static System.String bytesToString(sbyte[] bytes, int offset, int length, System.String encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.String tempStr;
|
||||
//UPGRADE_TODO: The differences in the Format of parameters for constructor 'java.lang.String.String' may cause compilation errors. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1092'"
|
||||
tempStr = System.Text.Encoding.GetEncoding(encoding).GetString(SupportClass.ToByteArray(bytes));
|
||||
return new System.String(tempStr.ToCharArray(), offset, length);
|
||||
}
|
||||
catch (System.IO.IOException uee)
|
||||
{
|
||||
// This should only be used when 'encoding' is an encoding that must necessarily
|
||||
// be supported by the JVM, like UTF-8
|
||||
//UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Throwable.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
|
||||
throw new System.SystemException("Platform does not support required encoding: " + uee);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
118
csharp/client/result/optional/NDEFRecord.cs
Executable file
118
csharp/client/result/optional/NDEFRecord.cs
Executable file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.client.result.optional
|
||||
{
|
||||
|
||||
/// <summary> <p>Represents a record in an NDEF message. This class only supports certain types
|
||||
/// of records -- namely, non-chunked records, where ID length is omitted, and only
|
||||
/// "short records".</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class NDEFRecord
|
||||
{
|
||||
internal bool MessageBegin
|
||||
{
|
||||
get
|
||||
{
|
||||
return (header & 0x80) != 0;
|
||||
}
|
||||
|
||||
}
|
||||
internal bool MessageEnd
|
||||
{
|
||||
get
|
||||
{
|
||||
return (header & 0x40) != 0;
|
||||
}
|
||||
|
||||
}
|
||||
internal System.String Type
|
||||
{
|
||||
get
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
internal sbyte[] Payload
|
||||
{
|
||||
get
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
|
||||
}
|
||||
internal int TotalRecordLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return totalRecordLength;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private const int SUPPORTED_HEADER_MASK = 0x3F; // 0 0 1 1 1 111 (the bottom 6 bits matter)
|
||||
private const int SUPPORTED_HEADER = 0x11; // 0 0 0 1 0 001
|
||||
|
||||
public const System.String TEXT_WELL_KNOWN_TYPE = "T";
|
||||
public const System.String URI_WELL_KNOWN_TYPE = "U";
|
||||
public const System.String SMART_POSTER_WELL_KNOWN_TYPE = "Sp";
|
||||
public const System.String ACTION_WELL_KNOWN_TYPE = "act";
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'header '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int header;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'type '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String type;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'payload '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private sbyte[] payload;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'totalRecordLength '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int totalRecordLength;
|
||||
|
||||
private NDEFRecord(int header, System.String type, sbyte[] payload, int totalRecordLength)
|
||||
{
|
||||
this.header = header;
|
||||
this.type = type;
|
||||
this.payload = payload;
|
||||
this.totalRecordLength = totalRecordLength;
|
||||
}
|
||||
|
||||
internal static NDEFRecord readRecord(sbyte[] bytes, int offset)
|
||||
{
|
||||
int header = bytes[offset] & 0xFF;
|
||||
// Does header match what we support in the bits we care about?
|
||||
// XOR figures out where we differ, and if any of those are in the mask, fail
|
||||
if (((header ^ SUPPORTED_HEADER) & SUPPORTED_HEADER_MASK) != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int typeLength = bytes[offset + 1] & 0xFF;
|
||||
|
||||
int payloadLength = bytes[offset + 2] & 0xFF;
|
||||
|
||||
System.String type = AbstractNDEFResultParser.bytesToString(bytes, offset + 3, typeLength, "US-ASCII");
|
||||
|
||||
sbyte[] payload = new sbyte[payloadLength];
|
||||
Array.Copy(bytes, offset + 3 + typeLength, payload, 0, payloadLength);
|
||||
|
||||
return new NDEFRecord(header, type, payload, 3 + typeLength + payloadLength);
|
||||
}
|
||||
}
|
||||
}
|
87
csharp/client/result/optional/NDEFSmartPosterParsedResult.cs
Executable file
87
csharp/client/result/optional/NDEFSmartPosterParsedResult.cs
Executable file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 ParsedResult = com.google.zxing.client.result.ParsedResult;
|
||||
using ParsedResultType = com.google.zxing.client.result.ParsedResultType;
|
||||
namespace com.google.zxing.client.result.optional
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class NDEFSmartPosterParsedResult:ParsedResult
|
||||
{
|
||||
public System.String Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String URI
|
||||
{
|
||||
get
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
|
||||
}
|
||||
public int Action
|
||||
{
|
||||
get
|
||||
{
|
||||
return action;
|
||||
}
|
||||
|
||||
}
|
||||
override public System.String DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
if (title == null)
|
||||
{
|
||||
return uri;
|
||||
}
|
||||
else
|
||||
{
|
||||
return title + '\n' + uri;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public const int ACTION_UNSPECIFIED = - 1;
|
||||
public const int ACTION_DO = 0;
|
||||
public const int ACTION_SAVE = 1;
|
||||
public const int ACTION_OPEN = 2;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'title '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String title;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'uri '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String uri;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'action '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int action;
|
||||
|
||||
internal NDEFSmartPosterParsedResult(int action, System.String uri, System.String title):base(ParsedResultType.NDEF_SMART_POSTER)
|
||||
{
|
||||
this.action = action;
|
||||
this.uri = uri;
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
}
|
96
csharp/client/result/optional/NDEFSmartPosterResultParser.cs
Executable file
96
csharp/client/result/optional/NDEFSmartPosterResultParser.cs
Executable file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.client.result.optional
|
||||
{
|
||||
|
||||
/// <summary> <p>Recognizes an NDEF message that encodes information according to the
|
||||
/// "Smart Poster Record Type Definition" specification.</p>
|
||||
///
|
||||
/// <p>This actually only supports some parts of the Smart Poster format: title,
|
||||
/// URI, and action records. Icon records are not supported because the size
|
||||
/// of these records are infeasibly large for barcodes. Size and type records
|
||||
/// are not supported. Multiple titles are not supported.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class NDEFSmartPosterResultParser:AbstractNDEFResultParser
|
||||
{
|
||||
|
||||
public static NDEFSmartPosterParsedResult parse(Result result)
|
||||
{
|
||||
sbyte[] bytes = result.RawBytes;
|
||||
if (bytes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
NDEFRecord headerRecord = NDEFRecord.readRecord(bytes, 0);
|
||||
// Yes, header record starts and ends a message
|
||||
if (headerRecord == null || !headerRecord.MessageBegin || !headerRecord.MessageEnd)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!headerRecord.Type.Equals(NDEFRecord.SMART_POSTER_WELL_KNOWN_TYPE))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
int recordNumber = 0;
|
||||
NDEFRecord ndefRecord = null;
|
||||
sbyte[] payload = headerRecord.Payload;
|
||||
int action = NDEFSmartPosterParsedResult.ACTION_UNSPECIFIED;
|
||||
System.String title = null;
|
||||
System.String uri = null;
|
||||
|
||||
while (offset < payload.Length && (ndefRecord = NDEFRecord.readRecord(payload, offset)) != null)
|
||||
{
|
||||
if (recordNumber == 0 && !ndefRecord.MessageBegin)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
System.String type = ndefRecord.Type;
|
||||
if (NDEFRecord.TEXT_WELL_KNOWN_TYPE.Equals(type))
|
||||
{
|
||||
System.String[] languageText = NDEFTextResultParser.decodeTextPayload(ndefRecord.Payload);
|
||||
title = languageText[1];
|
||||
}
|
||||
else if (NDEFRecord.URI_WELL_KNOWN_TYPE.Equals(type))
|
||||
{
|
||||
uri = NDEFURIResultParser.decodeURIPayload(ndefRecord.Payload);
|
||||
}
|
||||
else if (NDEFRecord.ACTION_WELL_KNOWN_TYPE.Equals(type))
|
||||
{
|
||||
action = ndefRecord.Payload[0];
|
||||
}
|
||||
recordNumber++;
|
||||
offset += ndefRecord.TotalRecordLength;
|
||||
}
|
||||
|
||||
if (recordNumber == 0 || (ndefRecord != null && !ndefRecord.MessageEnd))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NDEFSmartPosterParsedResult(action, uri, title);
|
||||
}
|
||||
}
|
||||
}
|
65
csharp/client/result/optional/NDEFTextResultParser.cs
Executable file
65
csharp/client/result/optional/NDEFTextResultParser.cs
Executable file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
using TextParsedResult = com.google.zxing.client.result.TextParsedResult;
|
||||
namespace com.google.zxing.client.result.optional
|
||||
{
|
||||
|
||||
/// <summary> Recognizes an NDEF message that encodes text according to the
|
||||
/// "Text Record Type Definition" specification.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class NDEFTextResultParser:AbstractNDEFResultParser
|
||||
{
|
||||
|
||||
public static TextParsedResult parse(Result result)
|
||||
{
|
||||
sbyte[] bytes = result.RawBytes;
|
||||
if (bytes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
NDEFRecord ndefRecord = NDEFRecord.readRecord(bytes, 0);
|
||||
if (ndefRecord == null || !ndefRecord.MessageBegin || !ndefRecord.MessageEnd)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!ndefRecord.Type.Equals(NDEFRecord.TEXT_WELL_KNOWN_TYPE))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String[] languageText = decodeTextPayload(ndefRecord.Payload);
|
||||
return new TextParsedResult(languageText[0], languageText[1]);
|
||||
}
|
||||
|
||||
internal static System.String[] decodeTextPayload(sbyte[] payload)
|
||||
{
|
||||
sbyte statusByte = payload[0];
|
||||
bool isUTF16 = (statusByte & 0x80) != 0;
|
||||
int languageLength = statusByte & 0x1F;
|
||||
// language is always ASCII-encoded:
|
||||
System.String language = bytesToString(payload, 1, languageLength, "US-ASCII");
|
||||
System.String encoding = isUTF16?"UTF-16":"UTF8";
|
||||
System.String text = bytesToString(payload, 1 + languageLength, payload.Length - languageLength - 1, encoding);
|
||||
return new System.String[]{language, text};
|
||||
}
|
||||
}
|
||||
}
|
68
csharp/client/result/optional/NDEFURIResultParser.cs
Executable file
68
csharp/client/result/optional/NDEFURIResultParser.cs
Executable file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
using URIParsedResult = com.google.zxing.client.result.URIParsedResult;
|
||||
namespace com.google.zxing.client.result.optional
|
||||
{
|
||||
|
||||
/// <summary> Recognizes an NDEF message that encodes a URI according to the
|
||||
/// "URI Record Type Definition" specification.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class NDEFURIResultParser:AbstractNDEFResultParser
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'URI_PREFIXES'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly System.String[] URI_PREFIXES = new System.String[]{null, "http://www.", "https://www.", "http://", "https://", "tel:", "mailto:", "ftp://anonymous:anonymous@", "ftp://ftp.", "ftps://", "sftp://", "smb://", "nfs://", "ftp://", "dav://", "news:", "telnet://", "imap:", "rtsp://", "urn:", "pop:", "sip:", "sips:", "tftp:", "btspp://", "btl2cap://", "btgoep://", "tcpobex://", "irdaobex://", "file://", "urn:epc:id:", "urn:epc:tag:", "urn:epc:pat:", "urn:epc:raw:", "urn:epc:", "urn:nfc:"};
|
||||
|
||||
public static URIParsedResult parse(Result result)
|
||||
{
|
||||
sbyte[] bytes = result.RawBytes;
|
||||
if (bytes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
NDEFRecord ndefRecord = NDEFRecord.readRecord(bytes, 0);
|
||||
if (ndefRecord == null || !ndefRecord.MessageBegin || !ndefRecord.MessageEnd)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!ndefRecord.Type.Equals(NDEFRecord.URI_WELL_KNOWN_TYPE))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
System.String fullURI = decodeURIPayload(ndefRecord.Payload);
|
||||
return new URIParsedResult(fullURI, null);
|
||||
}
|
||||
|
||||
internal static System.String decodeURIPayload(sbyte[] payload)
|
||||
{
|
||||
int identifierCode = payload[0] & 0xFF;
|
||||
System.String prefix = null;
|
||||
if (identifierCode < URI_PREFIXES.Length)
|
||||
{
|
||||
prefix = URI_PREFIXES[identifierCode];
|
||||
}
|
||||
System.String restOfURI = bytesToString(payload, 1, payload.Length - 1, "UTF8");
|
||||
return prefix == null?restOfURI:prefix + restOfURI;
|
||||
}
|
||||
}
|
||||
}
|
208
csharp/common/BitArray.cs
Executable file
208
csharp/common/BitArray.cs
Executable file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class BitArray
|
||||
{
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: I have changed these members to be public so ProGuard can inline get() and set(). Ideally
|
||||
// they'd be private and we'd use the -allowaccessmodification flag, but Dalvik rejects the
|
||||
// resulting binary at runtime on Android. If we find a solution to this, these should be changed
|
||||
// back to private.
|
||||
public int[] bits;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'size '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public int size;
|
||||
|
||||
public BitArray(int size)
|
||||
{
|
||||
if (size < 1)
|
||||
{
|
||||
throw new System.ArgumentException("size must be at least 1");
|
||||
}
|
||||
this.size = size;
|
||||
this.bits = makeArray(size);
|
||||
}
|
||||
|
||||
/// <param name="i">bit to get
|
||||
/// </param>
|
||||
/// <returns> true iff bit i is set
|
||||
/// </returns>
|
||||
public bool get_Renamed(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_Renamed(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);
|
||||
}
|
||||
|
||||
/// <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> 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>
|
||||
/// <throws> IllegalArgumentException if end is less than or equal to start </throws>
|
||||
public bool isRange(int start, int end, bool value_Renamed)
|
||||
{
|
||||
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_Renamed?mask:0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <returns> underlying array of ints. The first element holds the first 32 bits, and the least
|
||||
/// significant bit is bit 0.
|
||||
/// </returns>
|
||||
public int[] getBitArray()
|
||||
{
|
||||
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_Renamed(size - i - 1))
|
||||
{
|
||||
newBits[i >> 5] |= 1 << (i & 0x1F);
|
||||
}
|
||||
}
|
||||
bits = newBits;
|
||||
}
|
||||
|
||||
private static int[] makeArray(int size)
|
||||
{
|
||||
int arraySize = size >> 5;
|
||||
if ((size & 0x1F) != 0)
|
||||
{
|
||||
arraySize++;
|
||||
}
|
||||
return new int[arraySize];
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if ((i & 0x07) == 0)
|
||||
{
|
||||
result.Append(' ');
|
||||
}
|
||||
result.Append(get_Renamed(i)?'X':'.');
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
237
csharp/common/BitMatrix.cs
Executable file
237
csharp/common/BitMatrix.cs
Executable file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* 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;
|
||||
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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class BitMatrix
|
||||
{
|
||||
/// <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;
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary> This method is for compatibility with older code. It's only logical to call if the matrix
|
||||
/// is square, so I'm throwing if that's not the case.
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns> row/column dimension of this matrix
|
||||
/// </returns>
|
||||
public int Dimension
|
||||
{
|
||||
get
|
||||
{
|
||||
if (width != height)
|
||||
{
|
||||
throw new System.SystemException("Can't call getDimension() on a non-square matrix");
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Just like BitArray, these need to be public so ProGuard can inline them.
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'width '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public int width;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'height '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public int height;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'rowSize '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public int rowSize;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'bits '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public 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;
|
||||
int rowSize = width >> 5;
|
||||
if ((width & 0x1f) != 0)
|
||||
{
|
||||
rowSize++;
|
||||
}
|
||||
this.rowSize = rowSize;
|
||||
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_Renamed(int x, int y)
|
||||
{
|
||||
int offset = y * rowSize + (x >> 5);
|
||||
return ((SupportClass.URShift(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_Renamed(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;
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(height * (width + 1));
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
result.Append(get_Renamed(x, y)?"X ":" ");
|
||||
}
|
||||
result.Append('\n');
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
109
csharp/common/BitSource.cs
Executable file
109
csharp/common/BitSource.cs
Executable file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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;
|
||||
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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class BitSource
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'bytes '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private 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;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> IllegalArgumentException if numBits isn't in [1,32] </throws>
|
||||
public int readBits(int numBits)
|
||||
{
|
||||
if (numBits < 1 || numBits > 32)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
116
csharp/common/ByteArray.cs
Executable file
116
csharp/common/ByteArray.cs
Executable file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> This class implements an array of unsigned bytes.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ByteArray
|
||||
{
|
||||
public bool Empty
|
||||
{
|
||||
get
|
||||
{
|
||||
return size_Renamed_Field == 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private const int INITIAL_SIZE = 32;
|
||||
|
||||
private sbyte[] bytes;
|
||||
private int size_Renamed_Field;
|
||||
|
||||
public ByteArray()
|
||||
{
|
||||
bytes = null;
|
||||
size_Renamed_Field = 0;
|
||||
}
|
||||
|
||||
public ByteArray(int size)
|
||||
{
|
||||
bytes = new sbyte[size];
|
||||
this.size_Renamed_Field = size;
|
||||
}
|
||||
|
||||
public ByteArray(sbyte[] byteArray)
|
||||
{
|
||||
bytes = byteArray;
|
||||
size_Renamed_Field = bytes.Length;
|
||||
}
|
||||
|
||||
/// <summary> Access an unsigned byte at location index.</summary>
|
||||
/// <param name="index">The index in the array to access.
|
||||
/// </param>
|
||||
/// <returns> The unsigned value of the byte as an int.
|
||||
/// </returns>
|
||||
public int at(int index)
|
||||
{
|
||||
return bytes[index] & 0xff;
|
||||
}
|
||||
|
||||
public void set_Renamed(int index, int value_Renamed)
|
||||
{
|
||||
bytes[index] = (sbyte) value_Renamed;
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return size_Renamed_Field;
|
||||
}
|
||||
|
||||
public void appendByte(int value_Renamed)
|
||||
{
|
||||
if (size_Renamed_Field == 0 || size_Renamed_Field >= bytes.Length)
|
||||
{
|
||||
int newSize = System.Math.Max(INITIAL_SIZE, size_Renamed_Field << 1);
|
||||
reserve(newSize);
|
||||
}
|
||||
bytes[size_Renamed_Field] = (sbyte) value_Renamed;
|
||||
size_Renamed_Field++;
|
||||
}
|
||||
|
||||
public void reserve(int capacity)
|
||||
{
|
||||
if (bytes == null || bytes.Length < capacity)
|
||||
{
|
||||
sbyte[] newArray = new sbyte[capacity];
|
||||
if (bytes != null)
|
||||
{
|
||||
Array.Copy(bytes, 0, newArray, 0, bytes.Length);
|
||||
}
|
||||
bytes = newArray;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy count bytes from array source starting at offset.
|
||||
public void set_Renamed(sbyte[] source, int offset, int count)
|
||||
{
|
||||
bytes = new sbyte[count];
|
||||
size_Renamed_Field = count;
|
||||
for (int x = 0; x < count; x++)
|
||||
{
|
||||
bytes[x] = source[offset + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
131
csharp/common/ByteMatrix.cs
Executable file
131
csharp/common/ByteMatrix.cs
Executable file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> A class which wraps a 2D array of bytes. The default usage is signed. If you want to use it as a
|
||||
/// unsigned container, it's up to you to do byteValue & 0xff at each location.
|
||||
///
|
||||
/// JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned
|
||||
/// -1, 0, and 1, I'm going to use less memory and go with bytes.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ByteMatrix
|
||||
{
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
}
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
}
|
||||
public sbyte[][] Array
|
||||
{
|
||||
get
|
||||
{
|
||||
return bytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'bytes '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private sbyte[][] bytes;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'width '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int width;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'height '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int height;
|
||||
|
||||
public ByteMatrix(int width, int height)
|
||||
{
|
||||
bytes = new sbyte[height][];
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
bytes[i] = new sbyte[width];
|
||||
}
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public sbyte get_Renamed(int x, int y)
|
||||
{
|
||||
return bytes[y][x];
|
||||
}
|
||||
|
||||
public void set_Renamed(int x, int y, sbyte value_Renamed)
|
||||
{
|
||||
bytes[y][x] = value_Renamed;
|
||||
}
|
||||
|
||||
public void set_Renamed(int x, int y, int value_Renamed)
|
||||
{
|
||||
bytes[y][x] = (sbyte) value_Renamed;
|
||||
}
|
||||
|
||||
public void clear(sbyte value_Renamed)
|
||||
{
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
bytes[y][x] = value_Renamed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(2 * width * height + 2);
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
switch (bytes[y][x])
|
||||
{
|
||||
|
||||
case 0:
|
||||
result.Append(" 0");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
result.Append(" 1");
|
||||
break;
|
||||
|
||||
default:
|
||||
result.Append(" ");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
result.Append('\n');
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
126
csharp/common/CharacterSetECI.cs
Executable file
126
csharp/common/CharacterSetECI.cs
Executable file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
|
||||
/// of ISO 18004.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class CharacterSetECI:ECI
|
||||
{
|
||||
public System.String EncodingName
|
||||
{
|
||||
get
|
||||
{
|
||||
return encodingName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static System.Collections.Hashtable VALUE_TO_ECI;
|
||||
private static System.Collections.Hashtable NAME_TO_ECI;
|
||||
|
||||
private static void initialize()
|
||||
{
|
||||
VALUE_TO_ECI = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(29));
|
||||
NAME_TO_ECI = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(29));
|
||||
// TODO figure out if these values are even right!
|
||||
addCharacterSet(0, "Cp437");
|
||||
addCharacterSet(1, new System.String[]{"ISO8859_1", "ISO-8859-1"});
|
||||
addCharacterSet(2, "Cp437");
|
||||
addCharacterSet(3, new System.String[]{"ISO8859_1", "ISO-8859-1"});
|
||||
addCharacterSet(4, "ISO8859_2");
|
||||
addCharacterSet(5, "ISO8859_3");
|
||||
addCharacterSet(6, "ISO8859_4");
|
||||
addCharacterSet(7, "ISO8859_5");
|
||||
addCharacterSet(8, "ISO8859_6");
|
||||
addCharacterSet(9, "ISO8859_7");
|
||||
addCharacterSet(10, "ISO8859_8");
|
||||
addCharacterSet(11, "ISO8859_9");
|
||||
addCharacterSet(12, "ISO8859_10");
|
||||
addCharacterSet(13, "ISO8859_11");
|
||||
addCharacterSet(15, "ISO8859_13");
|
||||
addCharacterSet(16, "ISO8859_14");
|
||||
addCharacterSet(17, "ISO8859_15");
|
||||
addCharacterSet(18, "ISO8859_16");
|
||||
addCharacterSet(20, new System.String[]{"SJIS", "Shift_JIS"});
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'encodingName '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String encodingName;
|
||||
|
||||
private CharacterSetECI(int value_Renamed, System.String encodingName):base(value_Renamed)
|
||||
{
|
||||
this.encodingName = encodingName;
|
||||
}
|
||||
|
||||
private static void addCharacterSet(int value_Renamed, System.String encodingName)
|
||||
{
|
||||
CharacterSetECI eci = new CharacterSetECI(value_Renamed, encodingName);
|
||||
VALUE_TO_ECI[(System.Int32) value_Renamed] = eci; // can't use valueOf
|
||||
NAME_TO_ECI[encodingName] = eci;
|
||||
}
|
||||
|
||||
private static void addCharacterSet(int value_Renamed, System.String[] encodingNames)
|
||||
{
|
||||
CharacterSetECI eci = new CharacterSetECI(value_Renamed, encodingNames[0]);
|
||||
VALUE_TO_ECI[(System.Int32) value_Renamed] = eci; // can't use valueOf
|
||||
for (int i = 0; i < encodingNames.Length; i++)
|
||||
{
|
||||
NAME_TO_ECI[encodingNames[i]] = eci;
|
||||
}
|
||||
}
|
||||
|
||||
/// <param name="value">character set ECI value
|
||||
/// </param>
|
||||
/// <returns> {@link CharacterSetECI} representing ECI of given value, or null if it is legal but
|
||||
/// unsupported
|
||||
/// </returns>
|
||||
/// <throws> IllegalArgumentException if ECI value is invalid </throws>
|
||||
public static CharacterSetECI getCharacterSetECIByValue(int value_Renamed)
|
||||
{
|
||||
if (VALUE_TO_ECI == null)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
if (value_Renamed < 0 || value_Renamed >= 900)
|
||||
{
|
||||
throw new System.ArgumentException("Bad ECI value: " + value_Renamed);
|
||||
}
|
||||
return (CharacterSetECI) VALUE_TO_ECI[(System.Int32) value_Renamed];
|
||||
}
|
||||
|
||||
/// <param name="name">character set ECI encoding name
|
||||
/// </param>
|
||||
/// <returns> {@link CharacterSetECI} representing ECI for character encoding, or null if it is legal
|
||||
/// but unsupported
|
||||
/// </returns>
|
||||
public static CharacterSetECI getCharacterSetECIByName(System.String name)
|
||||
{
|
||||
if (NAME_TO_ECI == null)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
return (CharacterSetECI) NAME_TO_ECI[name];
|
||||
}
|
||||
}
|
||||
}
|
60
csharp/common/Collections.cs
Executable file
60
csharp/common/Collections.cs
Executable file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> <p>This is basically a substitute for <code>java.util.Collections</code>, which is not
|
||||
/// present in MIDP 2.0 / CLDC 1.1.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class Collections
|
||||
{
|
||||
|
||||
private Collections()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary> Sorts its argument (destructively) using insert sort; in the context of this package
|
||||
/// insertion sort is simple and efficient given its relatively small inputs.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="vector">vector to sort
|
||||
/// </param>
|
||||
/// <param name="comparator">comparator to define sort ordering
|
||||
/// </param>
|
||||
public static void insertionSort(System.Collections.ArrayList vector, Comparator comparator)
|
||||
{
|
||||
int max = vector.Count;
|
||||
for (int i = 1; i < max; i++)
|
||||
{
|
||||
System.Object value_Renamed = vector[i];
|
||||
int j = i - 1;
|
||||
System.Object valueB;
|
||||
while (j >= 0 && comparator.compare((valueB = vector[j]), value_Renamed) > 0)
|
||||
{
|
||||
vector[j + 1] = valueB;
|
||||
j--;
|
||||
}
|
||||
vector[j + 1] = value_Renamed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
csharp/common/Comparator.cs
Executable file
28
csharp/common/Comparator.cs
Executable file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> This is merely a clone of <code>Comparator</code> since it is not available in
|
||||
/// CLDC 1.1 / MIDP 2.0.
|
||||
/// </summary>
|
||||
public interface Comparator
|
||||
{
|
||||
|
||||
int compare(System.Object o1, System.Object o2);
|
||||
}
|
||||
}
|
86
csharp/common/DecoderResult.cs
Executable file
86
csharp/common/DecoderResult.cs
Executable file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 ErrorCorrectionLevel = com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> <p>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.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class DecoderResult
|
||||
{
|
||||
public sbyte[] RawBytes
|
||||
{
|
||||
get
|
||||
{
|
||||
return rawBytes;
|
||||
}
|
||||
|
||||
}
|
||||
public System.String Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
public System.Collections.ArrayList ByteSegments
|
||||
{
|
||||
get
|
||||
{
|
||||
return byteSegments;
|
||||
}
|
||||
|
||||
}
|
||||
public ErrorCorrectionLevel ECLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return ecLevel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'rawBytes '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private sbyte[] rawBytes;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'text '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.String text;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'byteSegments '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.Collections.ArrayList byteSegments;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ecLevel '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ErrorCorrectionLevel ecLevel;
|
||||
|
||||
public DecoderResult(sbyte[] rawBytes, System.String text, System.Collections.ArrayList byteSegments, ErrorCorrectionLevel ecLevel)
|
||||
{
|
||||
if (rawBytes == null && text == null)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
this.rawBytes = rawBytes;
|
||||
this.text = text;
|
||||
this.byteSegments = byteSegments;
|
||||
this.ecLevel = ecLevel;
|
||||
}
|
||||
}
|
||||
}
|
82
csharp/common/DefaultGridSampler.cs
Executable file
82
csharp/common/DefaultGridSampler.cs
Executable file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class DefaultGridSampler:GridSampler
|
||||
{
|
||||
|
||||
public override BitMatrix sampleGrid(BitMatrix image, int dimension, 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, dimension, transform);
|
||||
}
|
||||
|
||||
public override BitMatrix sampleGrid(BitMatrix image, int dimension, PerspectiveTransform transform)
|
||||
{
|
||||
BitMatrix bits = new BitMatrix(dimension);
|
||||
float[] points = new float[dimension << 1];
|
||||
for (int y = 0; y < dimension; y++)
|
||||
{
|
||||
int max = points.Length;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
float iValue = (float) y + 0.5f;
|
||||
for (int x = 0; x < max; x += 2)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
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)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
if (image.get_Renamed((int) points[x], (int) points[x + 1]))
|
||||
{
|
||||
// Black(-ish) pixel
|
||||
bits.set_Renamed(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 ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
}
|
||||
}
|
60
csharp/common/DetectorResult.cs
Executable file
60
csharp/common/DetectorResult.cs
Executable file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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 ResultPoint = com.google.zxing.ResultPoint;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class DetectorResult
|
||||
{
|
||||
public BitMatrix Bits
|
||||
{
|
||||
get
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
|
||||
}
|
||||
public ResultPoint[] Points
|
||||
{
|
||||
get
|
||||
{
|
||||
return points;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'bits '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private BitMatrix bits;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'points '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ResultPoint[] points;
|
||||
|
||||
public DetectorResult(BitMatrix bits, ResultPoint[] points)
|
||||
{
|
||||
this.bits = bits;
|
||||
this.points = points;
|
||||
}
|
||||
}
|
||||
}
|
66
csharp/common/ECI.cs
Executable file
66
csharp/common/ECI.cs
Executable file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <summary> Superclass of classes encapsulating types ECIs, according to "Extended Channel Interpretations"
|
||||
/// 5.3 of ISO 18004.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public abstract class ECI
|
||||
{
|
||||
virtual public int Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return value_Renamed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'value '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int value_Renamed;
|
||||
|
||||
internal ECI(int value_Renamed)
|
||||
{
|
||||
this.value_Renamed = value_Renamed;
|
||||
}
|
||||
|
||||
/// <param name="value">ECI value
|
||||
/// </param>
|
||||
/// <returns> {@link ECI} representing ECI of given value, or null if it is legal but unsupported
|
||||
/// </returns>
|
||||
/// <throws> IllegalArgumentException if ECI value is invalid </throws>
|
||||
public static ECI getECIByValue(int value_Renamed)
|
||||
{
|
||||
if (value_Renamed < 0 || value_Renamed > 999999)
|
||||
{
|
||||
throw new System.ArgumentException("Bad ECI value: " + value_Renamed);
|
||||
}
|
||||
if (value_Renamed < 900)
|
||||
{
|
||||
// Character set ECIs use 000000 - 000899
|
||||
return CharacterSetECI.getCharacterSetECIByValue(value_Renamed);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
250
csharp/common/GlobalHistogramBinarizer.cs
Executable file
250
csharp/common/GlobalHistogramBinarizer.cs
Executable file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* 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 Binarizer = com.google.zxing.Binarizer;
|
||||
using LuminanceSource = com.google.zxing.LuminanceSource;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public class GlobalHistogramBinarizer:Binarizer
|
||||
{
|
||||
override public BitMatrix BlackMatrix
|
||||
{
|
||||
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
|
||||
|
||||
get
|
||||
{
|
||||
LuminanceSource source = LuminanceSource;
|
||||
// Redivivus.in Java to c# Porting update
|
||||
// 30/01/2010
|
||||
// Added
|
||||
// START
|
||||
sbyte[] localLuminances;
|
||||
//END
|
||||
|
||||
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;
|
||||
// Redivivus.in Java to c# Porting update
|
||||
// 30/01/2010
|
||||
// Commented & Added
|
||||
// START
|
||||
//sbyte[] localLuminances = source.getRow(row, luminances);
|
||||
localLuminances = source.getRow(row, luminances);
|
||||
// END
|
||||
int right = (width << 2) / 5;
|
||||
for (int x = width / 5; x < right; x++)
|
||||
{
|
||||
int pixel = localLuminances[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.
|
||||
|
||||
localLuminances = source.Matrix; // Govinda : Removed sbyte []
|
||||
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_Renamed(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private const int LUMINANCE_BITS = 5;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'LUMINANCE_SHIFT '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'LUMINANCE_BUCKETS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
|
||||
|
||||
private sbyte[] luminances = null;
|
||||
private int[] buckets = null;
|
||||
|
||||
public GlobalHistogramBinarizer(LuminanceSource source):base(source)
|
||||
{
|
||||
}
|
||||
|
||||
// Applies simple sharpening to the row data to improve performance of the 1D Readers.
|
||||
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.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_Renamed(x);
|
||||
}
|
||||
left = center;
|
||||
center = right;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
public override Binarizer createBinarizer(LuminanceSource source)
|
||||
{
|
||||
return new GlobalHistogramBinarizer(source);
|
||||
}
|
||||
|
||||
private void initArrays(int luminanceSize)
|
||||
{
|
||||
if (luminances == null || luminances.Length < luminanceSize)
|
||||
{
|
||||
luminances = new sbyte[luminanceSize];
|
||||
}
|
||||
if (buckets == null)
|
||||
{
|
||||
buckets = new int[LUMINANCE_BUCKETS];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int x = 0; x < LUMINANCE_BUCKETS; x++)
|
||||
{
|
||||
buckets[x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
// TODO: It might be worth comparing the brightest and darkest pixels seen, rather than the
|
||||
// two peaks, to determine the contrast.
|
||||
if (secondPeak - firstPeak <= numBuckets >> 4)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
193
csharp/common/GridSampler.cs
Executable file
193
csharp/common/GridSampler.cs
Executable file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <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 {@link #setGridSampler(GridSampler)}
|
||||
/// with an instance of a class which implements this interface.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public abstract class GridSampler
|
||||
{
|
||||
/// <returns> the current implementation of {@link GridSampler}
|
||||
/// </returns>
|
||||
public static GridSampler Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return gridSampler;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static GridSampler gridSampler = new DefaultGridSampler();
|
||||
|
||||
/// <summary> Sets the implementation of {@link 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 void setGridSampler(GridSampler newGridSampler)
|
||||
{
|
||||
if (newGridSampler == null)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
gridSampler = newGridSampler;
|
||||
}
|
||||
|
||||
/// <summary> <p>Samples an image for a square matrix of bits of the given dimension. This is used to extract
|
||||
/// the black/white modules of a 2D barcode like a QR Code found in an image. Because this barcode
|
||||
/// may be rotated or perspective-distorted, the caller supplies four points in the source image
|
||||
/// that define known points in the barcode, so that the image may be sampled appropriately.</p>
|
||||
///
|
||||
/// <p>The last eight "from" parameters are four X/Y coordinate pairs of locations of points in
|
||||
/// the image that define some significant points in the image to be sample. For example,
|
||||
/// these may be the location of finder pattern in a QR Code.</p>
|
||||
///
|
||||
/// <p>The first eight "to" parameters are four X/Y coordinate pairs measured in the destination
|
||||
/// {@link BitMatrix}, from the top left, where the known points in the image given by the "from"
|
||||
/// parameters map to.</p>
|
||||
///
|
||||
/// <p>These 16 parameters define the transformation needed to sample the image.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="image">image to sample
|
||||
/// </param>
|
||||
/// <param name="dimension">width/height of {@link BitMatrix} to sample from image
|
||||
/// </param>
|
||||
/// <returns> {@link BitMatrix} representing a grid of points sampled from the image within a region
|
||||
/// defined by the "from" parameters
|
||||
/// </returns>
|
||||
/// <throws> ReaderException if image can't be sampled, for example, if the transformation defined </throws>
|
||||
/// <summary> by the given points is invalid or results in sampling outside the image boundaries
|
||||
/// </summary>
|
||||
public abstract BitMatrix sampleGrid(BitMatrix image, int dimension, 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);
|
||||
|
||||
public virtual BitMatrix sampleGrid(BitMatrix image, int dimension, PerspectiveTransform transform)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException if an endpoint is lies outside the image boundaries </throws>
|
||||
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)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int x = (int) points[offset];
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int y = (int) points[offset + 1];
|
||||
if (x < - 1 || x > width || y < - 1 || y > height)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
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)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int x = (int) points[offset];
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int y = (int) points[offset + 1];
|
||||
if (x < - 1 || x > width || y < - 1 || y > height)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
187
csharp/common/HybridBinarizer.cs
Executable file
187
csharp/common/HybridBinarizer.cs
Executable file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* 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 Binarizer = com.google.zxing.Binarizer;
|
||||
using LuminanceSource = com.google.zxing.LuminanceSource;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
namespace com.google.zxing.common
|
||||
{
|
||||
|
||||
/// <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.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class HybridBinarizer:GlobalHistogramBinarizer
|
||||
{
|
||||
override public BitMatrix BlackMatrix
|
||||
{
|
||||
get
|
||||
{
|
||||
binarizeEntireImage();
|
||||
return matrix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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 MINIMUM_DIMENSION = 40;
|
||||
|
||||
private BitMatrix matrix = null;
|
||||
|
||||
public HybridBinarizer(LuminanceSource source):base(source)
|
||||
{
|
||||
}
|
||||
|
||||
public override Binarizer createBinarizer(LuminanceSource source)
|
||||
{
|
||||
return new HybridBinarizer(source);
|
||||
}
|
||||
|
||||
// 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.
|
||||
private void binarizeEntireImage()
|
||||
{
|
||||
if (matrix == null)
|
||||
{
|
||||
LuminanceSource source = LuminanceSource;
|
||||
if (source.Width >= MINIMUM_DIMENSION && source.Height >= MINIMUM_DIMENSION)
|
||||
{
|
||||
sbyte[] luminances = source.Matrix;
|
||||
int width = source.Width;
|
||||
int height = source.Height;
|
||||
int subWidth = width >> 3;
|
||||
int subHeight = height >> 3;
|
||||
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width);
|
||||
|
||||
matrix = new BitMatrix(width, height);
|
||||
calculateThresholdForBlock(luminances, subWidth, subHeight, width, blackPoints, matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the image is too small, fall back to the global histogram approach.
|
||||
matrix = base.BlackMatrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each 8x8 block in the image, calculate the average black point using a 5x5 grid
|
||||
// of the blocks around it. Also handles the corner cases, but will ignore up to 7 pixels
|
||||
// on the right edge and 7 pixels at the bottom of the image if the overall dimensions are not
|
||||
// multiples of eight. In practice, leaving those pixels white does not seem to be a problem.
|
||||
private static void calculateThresholdForBlock(sbyte[] luminances, int subWidth, int subHeight, int stride, int[][] blackPoints, BitMatrix matrix)
|
||||
{
|
||||
for (int y = 0; y < subHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < subWidth; x++)
|
||||
{
|
||||
int left = (x > 1)?x:2;
|
||||
left = (left < subWidth - 2)?left:subWidth - 3;
|
||||
int top = (y > 1)?y:2;
|
||||
top = (top < subHeight - 2)?top:subHeight - 3;
|
||||
int sum = 0;
|
||||
for (int z = - 2; z <= 2; z++)
|
||||
{
|
||||
int[] blackRow = blackPoints[top + z];
|
||||
sum += blackRow[left - 2];
|
||||
sum += blackRow[left - 1];
|
||||
sum += blackRow[left];
|
||||
sum += blackRow[left + 1];
|
||||
sum += blackRow[left + 2];
|
||||
}
|
||||
int average = sum / 25;
|
||||
threshold8x8Block(luminances, x << 3, y << 3, average, stride, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Applies a single threshold to an 8x8 block of pixels.
|
||||
private static void threshold8x8Block(sbyte[] luminances, int xoffset, int yoffset, int threshold, int stride, BitMatrix matrix)
|
||||
{
|
||||
for (int y = 0; y < 8; y++)
|
||||
{
|
||||
int offset = (yoffset + y) * stride + xoffset;
|
||||
for (int x = 0; x < 8; x++)
|
||||
{
|
||||
int pixel = luminances[offset + x] & 0xff;
|
||||
if (pixel < threshold)
|
||||
{
|
||||
matrix.set_Renamed(xoffset + x, yoffset + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculates a single black point for each 8x8 block of pixels and saves it away.
|
||||
private static int[][] calculateBlackPoints(sbyte[] luminances, int subWidth, int subHeight, int stride)
|
||||
{
|
||||
int[][] blackPoints = new int[subHeight][];
|
||||
for (int i = 0; i < subHeight; i++)
|
||||
{
|
||||
blackPoints[i] = new int[subWidth];
|
||||
}
|
||||
for (int y = 0; y < subHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < subWidth; x++)
|
||||
{
|
||||
int sum = 0;
|
||||
int min = 255;
|
||||
int max = 0;
|
||||
for (int yy = 0; yy < 8; yy++)
|
||||
{
|
||||
int offset = ((y << 3) + yy) * stride + (x << 3);
|
||||
for (int xx = 0; xx < 8; xx++)
|
||||
{
|
||||
int pixel = luminances[offset + xx] & 0xff;
|
||||
sum += pixel;
|
||||
if (pixel < min)
|
||||
{
|
||||
min = pixel;
|
||||
}
|
||||
if (pixel > max)
|
||||
{
|
||||
max = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the contrast is inadequate, use half the minimum, so that this block will be
|
||||
// treated as part of the white background, but won't drag down neighboring blocks
|
||||
// too much.
|
||||
int average = (max - min > 24)?(sum >> 6):(min >> 1);
|
||||
blackPoints[y][x] = average;
|
||||
}
|
||||
}
|
||||
return blackPoints;
|
||||
}
|
||||
}
|
||||
}
|
146
csharp/common/PerspectiveTransform.cs
Executable file
146
csharp/common/PerspectiveTransform.cs
Executable file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* 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;
|
||||
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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class PerspectiveTransform
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a11 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a12 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a13 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a21 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a22 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a23 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a31 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a32 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'a33 '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private float a11;
|
||||
private float a12;
|
||||
private float a13;
|
||||
private float a21;
|
||||
private float a22;
|
||||
private float a23;
|
||||
private float a31;
|
||||
private float a32;
|
||||
private 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 dy2 = y3 - y2;
|
||||
float dy3 = y0 - y1 + y2 - y3;
|
||||
if (dy2 == 0.0f && dy3 == 0.0f)
|
||||
{
|
||||
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 dx3 = x0 - x1 + x2 - x3;
|
||||
float dy1 = y1 - 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);
|
||||
}
|
||||
}
|
||||
}
|
255
csharp/common/detector/MonochromeRectangleDetector.cs
Executable file
255
csharp/common/detector/MonochromeRectangleDetector.cs
Executable file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
using BitMatrix = com.google.zxing.common.BitMatrix;
|
||||
namespace com.google.zxing.common.detector
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class MonochromeRectangleDetector
|
||||
{
|
||||
|
||||
private const int MAX_MODULES = 32;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'image '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private 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> {@link 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>
|
||||
/// <throws> ReaderException if no Data Matrix Code can be found </throws>
|
||||
public ResultPoint[] detect()
|
||||
{
|
||||
int height = image.Height;
|
||||
int width = image.Width;
|
||||
int halfHeight = height >> 1;
|
||||
int halfWidth = width >> 1;
|
||||
int deltaY = System.Math.Max(1, height / (MAX_MODULES << 3));
|
||||
int deltaX = System.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);
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
top = (int) pointA.Y - 1;
|
||||
ResultPoint pointB = findCornerFromCenter(halfWidth, - deltaX, left, right, halfHeight, 0, top, bottom, halfHeight >> 1);
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
left = (int) pointB.X - 1;
|
||||
ResultPoint pointC = findCornerFromCenter(halfWidth, deltaX, left, right, halfHeight, 0, top, bottom, halfHeight >> 1);
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
right = (int) pointC.X + 1;
|
||||
ResultPoint pointD = findCornerFromCenter(halfWidth, 0, left, right, halfHeight, deltaY, top, bottom, halfWidth >> 1);
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
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 {@link com.google.zxing.ResultPoint} encapsulating the corner that was found
|
||||
/// </returns>
|
||||
/// <throws> com.google.zxing.ReaderException if such a point cannot be found </throws>
|
||||
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 ReaderException.Instance;
|
||||
}
|
||||
// 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 ReaderException.Instance;
|
||||
}
|
||||
|
||||
/// <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_Renamed(start, fixedDimension):image.get_Renamed(fixedDimension, start))
|
||||
{
|
||||
start--;
|
||||
}
|
||||
else
|
||||
{
|
||||
int whiteRunStart = start;
|
||||
do
|
||||
{
|
||||
start--;
|
||||
}
|
||||
while (start >= minDim && !(horizontal?image.get_Renamed(start, fixedDimension):image.get_Renamed(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_Renamed(end, fixedDimension):image.get_Renamed(fixedDimension, end))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int whiteRunStart = end;
|
||||
do
|
||||
{
|
||||
end++;
|
||||
}
|
||||
while (end < maxDim && !(horizontal?image.get_Renamed(end, fixedDimension):image.get_Renamed(fixedDimension, end)));
|
||||
int whiteRunSize = end - whiteRunStart;
|
||||
if (end >= maxDim || whiteRunSize > maxWhiteRun)
|
||||
{
|
||||
end = whiteRunStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
end--;
|
||||
|
||||
return end > start?new int[]{start, end}:null;
|
||||
}
|
||||
}
|
||||
}
|
174
csharp/common/reedsolomon/GF256.cs
Executable file
174
csharp/common/reedsolomon/GF256.cs
Executable file
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common.reedsolomon
|
||||
{
|
||||
|
||||
/// <summary> <p>This class contains utility methods for performing mathematical operations over
|
||||
/// the Galois Field GF(256). Operations use a given primitive polynomial in calculations.</p>
|
||||
///
|
||||
/// <p>Throughout this package, elements of GF(256) are represented as an <code>int</code>
|
||||
/// for convenience and speed (but at the cost of memory).
|
||||
/// Only the bottom 8 bits are really used.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class GF256
|
||||
{
|
||||
internal GF256Poly Zero
|
||||
{
|
||||
get
|
||||
{
|
||||
return zero;
|
||||
}
|
||||
|
||||
}
|
||||
internal GF256Poly One
|
||||
{
|
||||
get
|
||||
{
|
||||
return one;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'QR_CODE_FIELD '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly GF256 QR_CODE_FIELD = new GF256(0x011D); // x^8 + x^4 + x^3 + x^2 + 1
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'DATA_MATRIX_FIELD '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
public static readonly GF256 DATA_MATRIX_FIELD = new GF256(0x012D); // x^8 + x^5 + x^3 + x^2 + 1
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'expTable '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int[] expTable;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'logTable '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int[] logTable;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'zero '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private GF256Poly zero;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'one '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private GF256Poly one;
|
||||
|
||||
/// <summary> Create a representation of GF(256) using the given primitive polynomial.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="primitive">irreducible polynomial whose coefficients are represented by
|
||||
/// the bits of an int, where the least-significant bit represents the constant
|
||||
/// coefficient
|
||||
/// </param>
|
||||
private GF256(int primitive)
|
||||
{
|
||||
expTable = new int[256];
|
||||
logTable = new int[256];
|
||||
int x = 1;
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
expTable[i] = x;
|
||||
x <<= 1; // x = x * 2; we're assuming the generator alpha is 2
|
||||
if (x >= 0x100)
|
||||
{
|
||||
x ^= primitive;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 255; i++)
|
||||
{
|
||||
logTable[expTable[i]] = i;
|
||||
}
|
||||
// logTable[0] == 0 but this should never be used
|
||||
zero = new GF256Poly(this, new int[]{0});
|
||||
one = new GF256Poly(this, new int[]{1});
|
||||
}
|
||||
|
||||
/// <returns> the monomial representing coefficient * x^degree
|
||||
/// </returns>
|
||||
internal GF256Poly buildMonomial(int degree, int coefficient)
|
||||
{
|
||||
if (degree < 0)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
if (coefficient == 0)
|
||||
{
|
||||
return zero;
|
||||
}
|
||||
int[] coefficients = new int[degree + 1];
|
||||
coefficients[0] = coefficient;
|
||||
return new GF256Poly(this, coefficients);
|
||||
}
|
||||
|
||||
/// <summary> Implements both addition and subtraction -- they are the same in GF(256).
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns> sum/difference of a and b
|
||||
/// </returns>
|
||||
internal static int addOrSubtract(int a, int b)
|
||||
{
|
||||
return a ^ b;
|
||||
}
|
||||
|
||||
/// <returns> 2 to the power of a in GF(256)
|
||||
/// </returns>
|
||||
internal int exp(int a)
|
||||
{
|
||||
return expTable[a];
|
||||
}
|
||||
|
||||
/// <returns> base 2 log of a in GF(256)
|
||||
/// </returns>
|
||||
internal int log(int a)
|
||||
{
|
||||
if (a == 0)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
return logTable[a];
|
||||
}
|
||||
|
||||
/// <returns> multiplicative inverse of a
|
||||
/// </returns>
|
||||
internal int inverse(int a)
|
||||
{
|
||||
if (a == 0)
|
||||
{
|
||||
throw new System.ArithmeticException();
|
||||
}
|
||||
return expTable[255 - logTable[a]];
|
||||
}
|
||||
|
||||
/// <param name="a">
|
||||
/// </param>
|
||||
/// <param name="b">
|
||||
/// </param>
|
||||
/// <returns> product of a and b in GF(256)
|
||||
/// </returns>
|
||||
internal int multiply(int a, int b)
|
||||
{
|
||||
if (a == 0 || b == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (a == 1)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
if (b == 1)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
return expTable[(logTable[a] + logTable[b]) % 255];
|
||||
}
|
||||
}
|
||||
}
|
328
csharp/common/reedsolomon/GF256Poly.cs
Executable file
328
csharp/common/reedsolomon/GF256Poly.cs
Executable file
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common.reedsolomon
|
||||
{
|
||||
|
||||
/// <summary> <p>Represents a polynomial whose coefficients are elements of GF(256).
|
||||
/// Instances of this class are immutable.</p>
|
||||
///
|
||||
/// <p>Much credit is due to William Rucklidge since portions of this code are an indirect
|
||||
/// port of his C++ Reed-Solomon implementation.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class GF256Poly
|
||||
{
|
||||
internal int[] Coefficients
|
||||
{
|
||||
get
|
||||
{
|
||||
return coefficients;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> degree of this polynomial
|
||||
/// </returns>
|
||||
internal int Degree
|
||||
{
|
||||
get
|
||||
{
|
||||
return coefficients.Length - 1;
|
||||
}
|
||||
|
||||
}
|
||||
/// <returns> true iff this polynomial is the monomial "0"
|
||||
/// </returns>
|
||||
internal bool Zero
|
||||
{
|
||||
get
|
||||
{
|
||||
return coefficients[0] == 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'field '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private GF256 field;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'coefficients '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int[] coefficients;
|
||||
|
||||
/// <param name="field">the {@link GF256} instance representing the field to use
|
||||
/// to perform computations
|
||||
/// </param>
|
||||
/// <param name="coefficients">coefficients as ints representing elements of GF(256), arranged
|
||||
/// from most significant (highest-power term) coefficient to least significant
|
||||
/// </param>
|
||||
/// <throws> IllegalArgumentException if argument is null or empty, </throws>
|
||||
/// <summary> or if leading coefficient is 0 and this is not a
|
||||
/// constant polynomial (that is, it is not the monomial "0")
|
||||
/// </summary>
|
||||
internal GF256Poly(GF256 field, int[] coefficients)
|
||||
{
|
||||
if (coefficients == null || coefficients.Length == 0)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
this.field = field;
|
||||
int coefficientsLength = coefficients.Length;
|
||||
if (coefficientsLength > 1 && coefficients[0] == 0)
|
||||
{
|
||||
// Leading term must be non-zero for anything except the constant polynomial "0"
|
||||
int firstNonZero = 1;
|
||||
while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0)
|
||||
{
|
||||
firstNonZero++;
|
||||
}
|
||||
if (firstNonZero == coefficientsLength)
|
||||
{
|
||||
this.coefficients = field.Zero.coefficients;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.coefficients = new int[coefficientsLength - firstNonZero];
|
||||
Array.Copy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.coefficients = coefficients;
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns> coefficient of x^degree term in this polynomial
|
||||
/// </returns>
|
||||
internal int getCoefficient(int degree)
|
||||
{
|
||||
return coefficients[coefficients.Length - 1 - degree];
|
||||
}
|
||||
|
||||
/// <returns> evaluation of this polynomial at a given point
|
||||
/// </returns>
|
||||
internal int evaluateAt(int a)
|
||||
{
|
||||
if (a == 0)
|
||||
{
|
||||
// Just return the x^0 coefficient
|
||||
return getCoefficient(0);
|
||||
}
|
||||
int size = coefficients.Length;
|
||||
if (a == 1)
|
||||
{
|
||||
// Just the sum of the coefficients
|
||||
int result = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
result = GF256.addOrSubtract(result, coefficients[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int result2 = coefficients[0];
|
||||
for (int i = 1; i < size; i++)
|
||||
{
|
||||
result2 = GF256.addOrSubtract(field.multiply(a, result2), coefficients[i]);
|
||||
}
|
||||
return result2;
|
||||
}
|
||||
|
||||
internal GF256Poly addOrSubtract(GF256Poly other)
|
||||
{
|
||||
if (!field.Equals(other.field))
|
||||
{
|
||||
throw new System.ArgumentException("GF256Polys do not have same GF256 field");
|
||||
}
|
||||
if (Zero)
|
||||
{
|
||||
return other;
|
||||
}
|
||||
if (other.Zero)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
int[] smallerCoefficients = this.coefficients;
|
||||
int[] largerCoefficients = other.coefficients;
|
||||
if (smallerCoefficients.Length > largerCoefficients.Length)
|
||||
{
|
||||
int[] temp = smallerCoefficients;
|
||||
smallerCoefficients = largerCoefficients;
|
||||
largerCoefficients = temp;
|
||||
}
|
||||
int[] sumDiff = new int[largerCoefficients.Length];
|
||||
int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length;
|
||||
// Copy high-order terms only found in higher-degree polynomial's coefficients
|
||||
Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff);
|
||||
|
||||
for (int i = lengthDiff; i < largerCoefficients.Length; i++)
|
||||
{
|
||||
sumDiff[i] = GF256.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
|
||||
}
|
||||
|
||||
return new GF256Poly(field, sumDiff);
|
||||
}
|
||||
|
||||
internal GF256Poly multiply(GF256Poly other)
|
||||
{
|
||||
if (!field.Equals(other.field))
|
||||
{
|
||||
throw new System.ArgumentException("GF256Polys do not have same GF256 field");
|
||||
}
|
||||
if (Zero || other.Zero)
|
||||
{
|
||||
return field.Zero;
|
||||
}
|
||||
int[] aCoefficients = this.coefficients;
|
||||
int aLength = aCoefficients.Length;
|
||||
int[] bCoefficients = other.coefficients;
|
||||
int bLength = bCoefficients.Length;
|
||||
int[] product = new int[aLength + bLength - 1];
|
||||
for (int i = 0; i < aLength; i++)
|
||||
{
|
||||
int aCoeff = aCoefficients[i];
|
||||
for (int j = 0; j < bLength; j++)
|
||||
{
|
||||
product[i + j] = GF256.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));
|
||||
}
|
||||
}
|
||||
return new GF256Poly(field, product);
|
||||
}
|
||||
|
||||
internal GF256Poly multiply(int scalar)
|
||||
{
|
||||
if (scalar == 0)
|
||||
{
|
||||
return field.Zero;
|
||||
}
|
||||
if (scalar == 1)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
int size = coefficients.Length;
|
||||
int[] product = new int[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
product[i] = field.multiply(coefficients[i], scalar);
|
||||
}
|
||||
return new GF256Poly(field, product);
|
||||
}
|
||||
|
||||
internal GF256Poly multiplyByMonomial(int degree, int coefficient)
|
||||
{
|
||||
if (degree < 0)
|
||||
{
|
||||
throw new System.ArgumentException();
|
||||
}
|
||||
if (coefficient == 0)
|
||||
{
|
||||
return field.Zero;
|
||||
}
|
||||
int size = coefficients.Length;
|
||||
int[] product = new int[size + degree];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
product[i] = field.multiply(coefficients[i], coefficient);
|
||||
}
|
||||
return new GF256Poly(field, product);
|
||||
}
|
||||
|
||||
internal GF256Poly[] divide(GF256Poly other)
|
||||
{
|
||||
if (!field.Equals(other.field))
|
||||
{
|
||||
throw new System.ArgumentException("GF256Polys do not have same GF256 field");
|
||||
}
|
||||
if (other.Zero)
|
||||
{
|
||||
throw new System.ArgumentException("Divide by 0");
|
||||
}
|
||||
|
||||
GF256Poly quotient = field.Zero;
|
||||
GF256Poly remainder = this;
|
||||
|
||||
int denominatorLeadingTerm = other.getCoefficient(other.Degree);
|
||||
int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);
|
||||
|
||||
while (remainder.Degree >= other.Degree && !remainder.Zero)
|
||||
{
|
||||
int degreeDifference = remainder.Degree - other.Degree;
|
||||
int scale = field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm);
|
||||
GF256Poly term = other.multiplyByMonomial(degreeDifference, scale);
|
||||
GF256Poly iterationQuotient = field.buildMonomial(degreeDifference, scale);
|
||||
quotient = quotient.addOrSubtract(iterationQuotient);
|
||||
remainder = remainder.addOrSubtract(term);
|
||||
}
|
||||
|
||||
return new GF256Poly[]{quotient, remainder};
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(8 * Degree);
|
||||
for (int degree = Degree; degree >= 0; degree--)
|
||||
{
|
||||
int coefficient = getCoefficient(degree);
|
||||
if (coefficient != 0)
|
||||
{
|
||||
if (coefficient < 0)
|
||||
{
|
||||
result.Append(" - ");
|
||||
coefficient = - coefficient;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result.Length > 0)
|
||||
{
|
||||
result.Append(" + ");
|
||||
}
|
||||
}
|
||||
if (degree == 0 || coefficient != 1)
|
||||
{
|
||||
int alphaPower = field.log(coefficient);
|
||||
if (alphaPower == 0)
|
||||
{
|
||||
result.Append('1');
|
||||
}
|
||||
else if (alphaPower == 1)
|
||||
{
|
||||
result.Append('a');
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append("a^");
|
||||
result.Append(alphaPower);
|
||||
}
|
||||
}
|
||||
if (degree != 0)
|
||||
{
|
||||
if (degree == 1)
|
||||
{
|
||||
result.Append('x');
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append("x^");
|
||||
result.Append(degree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
217
csharp/common/reedsolomon/ReedSolomonDecoder.cs
Executable file
217
csharp/common/reedsolomon/ReedSolomonDecoder.cs
Executable file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* 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;
|
||||
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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> William Rucklidge
|
||||
/// </author>
|
||||
/// <author> sanfordsquires
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ReedSolomonDecoder
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'field '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private GF256 field;
|
||||
|
||||
public ReedSolomonDecoder(GF256 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>
|
||||
/// <throws> ReedSolomonException if decoding fails for any reason </throws>
|
||||
public void decode(int[] received, int twoS)
|
||||
{
|
||||
GF256Poly poly = new GF256Poly(field, received);
|
||||
int[] syndromeCoefficients = new int[twoS];
|
||||
bool dataMatrix = field.Equals(GF256.DATA_MATRIX_FIELD);
|
||||
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 ;
|
||||
}
|
||||
GF256Poly syndrome = new GF256Poly(field, syndromeCoefficients);
|
||||
GF256Poly[] sigmaOmega = runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);
|
||||
GF256Poly sigma = sigmaOmega[0];
|
||||
GF256Poly 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] = GF256.addOrSubtract(received[position], errorMagnitudes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private GF256Poly[] runEuclideanAlgorithm(GF256Poly a, GF256Poly b, int R)
|
||||
{
|
||||
// Assume a's degree is >= b's
|
||||
if (a.Degree < b.Degree)
|
||||
{
|
||||
GF256Poly temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
GF256Poly rLast = a;
|
||||
GF256Poly r = b;
|
||||
GF256Poly sLast = field.One;
|
||||
GF256Poly s = field.Zero;
|
||||
GF256Poly tLast = field.Zero;
|
||||
GF256Poly t = field.One;
|
||||
|
||||
// Run Euclidean algorithm until r's degree is less than R/2
|
||||
while (r.Degree >= R / 2)
|
||||
{
|
||||
GF256Poly rLastLast = rLast;
|
||||
GF256Poly sLastLast = sLast;
|
||||
GF256Poly tLastLast = tLast;
|
||||
rLast = r;
|
||||
sLast = s;
|
||||
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;
|
||||
GF256Poly 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));
|
||||
}
|
||||
|
||||
s = q.multiply(sLast).addOrSubtract(sLastLast);
|
||||
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);
|
||||
GF256Poly sigma = t.multiply(inverse);
|
||||
GF256Poly omega = r.multiply(inverse);
|
||||
return new GF256Poly[]{sigma, omega};
|
||||
}
|
||||
|
||||
private int[] findErrorLocations(GF256Poly 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 < 256 && 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(GF256Poly 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, GF256.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
89
csharp/common/reedsolomon/ReedSolomonEncoder.cs
Executable file
89
csharp/common/reedsolomon/ReedSolomonEncoder.cs
Executable file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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;
|
||||
namespace com.google.zxing.common.reedsolomon
|
||||
{
|
||||
|
||||
/// <summary> <p>Implements Reed-Solomon enbcoding, as the name implies.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> William Rucklidge
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ReedSolomonEncoder
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'field '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private GF256 field;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'cachedGenerators '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.Collections.ArrayList cachedGenerators;
|
||||
|
||||
public ReedSolomonEncoder(GF256 field)
|
||||
{
|
||||
if (!GF256.QR_CODE_FIELD.Equals(field))
|
||||
{
|
||||
throw new System.ArgumentException("Only QR Code is supported at this time");
|
||||
}
|
||||
this.field = field;
|
||||
this.cachedGenerators = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
cachedGenerators.Add(new GF256Poly(field, new int[]{1}));
|
||||
}
|
||||
|
||||
private GF256Poly buildGenerator(int degree)
|
||||
{
|
||||
if (degree >= cachedGenerators.Count)
|
||||
{
|
||||
GF256Poly lastGenerator = (GF256Poly) cachedGenerators[cachedGenerators.Count - 1];
|
||||
for (int d = cachedGenerators.Count; d <= degree; d++)
|
||||
{
|
||||
GF256Poly nextGenerator = lastGenerator.multiply(new GF256Poly(field, new int[]{1, field.exp(d - 1)}));
|
||||
cachedGenerators.Add(nextGenerator);
|
||||
lastGenerator = nextGenerator;
|
||||
}
|
||||
}
|
||||
return (GF256Poly) 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");
|
||||
}
|
||||
GF256Poly generator = buildGenerator(ecBytes);
|
||||
int[] infoCoefficients = new int[dataBytes];
|
||||
Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
||||
GF256Poly info = new GF256Poly(field, infoCoefficients);
|
||||
info = info.multiplyByMonomial(ecBytes, 1);
|
||||
GF256Poly 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);
|
||||
}
|
||||
}
|
||||
}
|
36
csharp/common/reedsolomon/ReedSolomonException.cs
Executable file
36
csharp/common/reedsolomon/ReedSolomonException.cs
Executable file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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;
|
||||
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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
[Serializable]
|
||||
public sealed class ReedSolomonException:System.Exception
|
||||
{
|
||||
|
||||
public ReedSolomonException(System.String message):base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
171
csharp/datamatrix/DataMatrixReader.cs
Executable file
171
csharp/datamatrix/DataMatrixReader.cs
Executable file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using DecodeHintType = com.google.zxing.DecodeHintType;
|
||||
using BinaryBitmap = com.google.zxing.BinaryBitmap;
|
||||
using Reader = com.google.zxing.Reader;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
using ResultMetadataType = com.google.zxing.ResultMetadataType;
|
||||
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;
|
||||
namespace com.google.zxing.datamatrix
|
||||
{
|
||||
|
||||
/// <summary> This implementation can detect and decode Data Matrix codes in an image.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> bbrown@google.com (Brian Brown)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class DataMatrixReader : Reader
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'NO_POINTS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0];
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'decoder '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private 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>
|
||||
/// <throws> ReaderException if a Data Matrix code cannot be found, or cannot be decoded </throws>
|
||||
public Result decode(BinaryBitmap image)
|
||||
{
|
||||
return decode(image, null);
|
||||
}
|
||||
|
||||
public Result decode(BinaryBitmap image, System.Collections.Hashtable 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.DATAMATRIX);
|
||||
if (decoderResult.ByteSegments != null)
|
||||
{
|
||||
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.ByteSegments);
|
||||
}
|
||||
if (decoderResult.ECLevel != null)
|
||||
{
|
||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel.ToString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary> This method detects a Data Matrix code in a "pure" image -- that is, pure monochrome image
|
||||
/// which contains only an unrotated, unskewed, image of a Data Matrix code, with some white border
|
||||
/// around it. This is a specialized method that works exceptionally fast in this special
|
||||
/// case.
|
||||
/// </summary>
|
||||
private static BitMatrix extractPureBits(BitMatrix image)
|
||||
{
|
||||
// Now need to determine module size in pixels
|
||||
|
||||
int height = image.Height;
|
||||
int width = image.Width;
|
||||
int minDimension = System.Math.Min(height, width);
|
||||
|
||||
// First, skip white border by tracking diagonally from the top left down and to the right:
|
||||
int borderWidth = 0;
|
||||
while (borderWidth < minDimension && !image.get_Renamed(borderWidth, borderWidth))
|
||||
{
|
||||
borderWidth++;
|
||||
}
|
||||
if (borderWidth == minDimension)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
// And then keep tracking across the top-left black module to determine module size
|
||||
int moduleEnd = borderWidth + 1;
|
||||
while (moduleEnd < width && image.get_Renamed(moduleEnd, borderWidth))
|
||||
{
|
||||
moduleEnd++;
|
||||
}
|
||||
if (moduleEnd == width)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
int moduleSize = moduleEnd - borderWidth;
|
||||
|
||||
// And now find where the bottommost black module on the first column ends
|
||||
int columnEndOfSymbol = height - 1;
|
||||
while (columnEndOfSymbol >= 0 && !image.get_Renamed(borderWidth, columnEndOfSymbol))
|
||||
{
|
||||
columnEndOfSymbol--;
|
||||
}
|
||||
if (columnEndOfSymbol < 0)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
columnEndOfSymbol++;
|
||||
|
||||
// Make sure width of barcode is a multiple of module size
|
||||
if ((columnEndOfSymbol - borderWidth) % moduleSize != 0)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
int dimension = (columnEndOfSymbol - borderWidth) / moduleSize;
|
||||
|
||||
// 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.
|
||||
borderWidth += (moduleSize >> 1);
|
||||
|
||||
int sampleDimension = borderWidth + (dimension - 1) * moduleSize;
|
||||
if (sampleDimension >= width || sampleDimension >= height)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
// Now just read off the bits
|
||||
BitMatrix bits = new BitMatrix(dimension);
|
||||
for (int i = 0; i < dimension; i++)
|
||||
{
|
||||
int iOffset = borderWidth + i * moduleSize;
|
||||
for (int j = 0; j < dimension; j++)
|
||||
{
|
||||
if (image.get_Renamed(borderWidth + j * moduleSize, iOffset))
|
||||
{
|
||||
bits.set_Renamed(j, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
}
|
||||
}
|
547
csharp/datamatrix/decoder/BitMatrixParser.cs
Executable file
547
csharp/datamatrix/decoder/BitMatrixParser.cs
Executable file
|
@ -0,0 +1,547 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
using BitMatrix = com.google.zxing.common.BitMatrix;
|
||||
namespace com.google.zxing.datamatrix.decoder
|
||||
{
|
||||
|
||||
/// <author> bbrown@google.com (Brian Brown)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class BitMatrixParser
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'mappingBitMatrix '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private BitMatrix mappingBitMatrix;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'readMappingMatrix '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private BitMatrix readMappingMatrix;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'version '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private Version version;
|
||||
|
||||
/// <param name="bitMatrix">{@link BitMatrix} to parse
|
||||
/// </param>
|
||||
/// <throws> ReaderException if dimension is < 10 or > 144 or not 0 mod 2 </throws>
|
||||
internal BitMatrixParser(BitMatrix bitMatrix)
|
||||
{
|
||||
int dimension = bitMatrix.Dimension;
|
||||
if (dimension < 10 || dimension > 144 || (dimension & 0x01) != 0)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
version = readVersion(bitMatrix);
|
||||
this.mappingBitMatrix = extractDataRegion(bitMatrix);
|
||||
// TODO(bbrown): Make this work for rectangular symbols
|
||||
this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.Dimension);
|
||||
}
|
||||
|
||||
/// <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 {@link BitMatrix} including alignment patterns
|
||||
/// </param>
|
||||
/// <returns> {@link Version} encapsulating the Data Matrix Code's "version"
|
||||
/// </returns>
|
||||
/// <throws> ReaderException if the dimensions of the mapping matrix are not valid </throws>
|
||||
/// <summary> Data Matrix dimensions.
|
||||
/// </summary>
|
||||
internal Version readVersion(BitMatrix bitMatrix)
|
||||
{
|
||||
|
||||
if (version != null)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
// TODO(bbrown): make this work for rectangular dimensions as well.
|
||||
int numRows = bitMatrix.Dimension;
|
||||
int numColumns = numRows;
|
||||
|
||||
return Version.getVersionForDimensions(numRows, numColumns);
|
||||
}
|
||||
|
||||
/// <summary> <p>Reads the bits in the {@link 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>
|
||||
/// <throws> ReaderException if the exact number of bytes expected is not read </throws>
|
||||
internal sbyte[] readCodewords()
|
||||
{
|
||||
|
||||
sbyte[] result = new sbyte[version.TotalCodewords];
|
||||
int resultOffset = 0;
|
||||
|
||||
int row = 4;
|
||||
int column = 0;
|
||||
// TODO(bbrown): Data Matrix can be rectangular, assuming square for now
|
||||
int numRows = mappingBitMatrix.Dimension;
|
||||
int numColumns = numRows;
|
||||
|
||||
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_Renamed(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_Renamed(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 ReaderException.Instance;
|
||||
}
|
||||
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_Renamed(column, row);
|
||||
return mappingBitMatrix.get_Renamed(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 {@link BitMatrix} that contains
|
||||
/// alignment patterns.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bitMatrix">Original {@link 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;
|
||||
|
||||
// TODO(bbrown): Make this work with rectangular codes
|
||||
if (bitMatrix.Dimension != 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;
|
||||
|
||||
// TODO(bbrown): Make this work with rectangular codes
|
||||
BitMatrix bitMatrixWithoutAlignment = new BitMatrix(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_Renamed(readColumnOffset, readRowOffset))
|
||||
{
|
||||
int writeColumnOffset = dataRegionColumnOffset + j;
|
||||
bitMatrixWithoutAlignment.set_Renamed(writeColumnOffset, writeRowOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bitMatrixWithoutAlignment;
|
||||
}
|
||||
}
|
||||
}
|
144
csharp/datamatrix/decoder/DataBlock.cs
Executable file
144
csharp/datamatrix/decoder/DataBlock.cs
Executable file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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;
|
||||
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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> bbrown@google.com (Brian Brown)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class DataBlock
|
||||
{
|
||||
internal int NumDataCodewords
|
||||
{
|
||||
get
|
||||
{
|
||||
return numDataCodewords;
|
||||
}
|
||||
|
||||
}
|
||||
internal sbyte[] Codewords
|
||||
{
|
||||
get
|
||||
{
|
||||
return codewords;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'numDataCodewords '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int numDataCodewords;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'codewords '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private 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> {@link DataBlock}s 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.getECBlocks();
|
||||
|
||||
// First count the total number of data blocks
|
||||
int totalBlocks = 0;
|
||||
Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();
|
||||
for (int i = 0; i < ecBlockArray.Length; i++)
|
||||
{
|
||||
totalBlocks += ecBlockArray[i].Count;
|
||||
}
|
||||
|
||||
// Now establish DataBlocks of the appropriate size and number of data codewords
|
||||
DataBlock[] result = new DataBlock[totalBlocks];
|
||||
int numResultBlocks = 0;
|
||||
for (int j = 0; j < ecBlockArray.Length; j++)
|
||||
{
|
||||
Version.ECB ecBlock = ecBlockArray[j];
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
625
csharp/datamatrix/decoder/DecodedBitStreamParser.cs
Executable file
625
csharp/datamatrix/decoder/DecodedBitStreamParser.cs
Executable file
|
@ -0,0 +1,625 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
using BitSource = com.google.zxing.common.BitSource;
|
||||
using DecoderResult = com.google.zxing.common.DecoderResult;
|
||||
namespace com.google.zxing.datamatrix.decoder
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> bbrown@google.com (Brian Brown)
|
||||
/// </author>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class DecodedBitStreamParser
|
||||
{
|
||||
|
||||
/// <summary> See ISO 16022:2006, Annex C Table C.1
|
||||
/// The C40 Basic Character Set (*'s used for placeholders for the shift values)
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'C40_BASIC_SET_CHARS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly char[] C40_BASIC_SET_CHARS = new char[]{'*', '*', '*', ' ', '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'};
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'C40_SHIFT2_SET_CHARS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly char[] C40_SHIFT2_SET_CHARS = new char[]{'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_'};
|
||||
|
||||
/// <summary> See ISO 16022:2006, Annex C Table C.2
|
||||
/// The Text Basic Character Set (*'s used for placeholders for the shift values)
|
||||
/// </summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'TEXT_BASIC_SET_CHARS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly char[] TEXT_BASIC_SET_CHARS = new char[]{'*', '*', '*', ' ', '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 char[] TEXT_SHIFT3_SET_CHARS = new char[]{'\'', '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 const int PAD_ENCODE = 0; // Not really an encoding
|
||||
private const int ASCII_ENCODE = 1;
|
||||
private const int C40_ENCODE = 2;
|
||||
private const int TEXT_ENCODE = 3;
|
||||
private const int ANSIX12_ENCODE = 4;
|
||||
private const int EDIFACT_ENCODE = 5;
|
||||
private const int BASE256_ENCODE = 6;
|
||||
|
||||
private DecodedBitStreamParser()
|
||||
{
|
||||
}
|
||||
|
||||
internal static DecoderResult decode(sbyte[] bytes)
|
||||
{
|
||||
BitSource bits = new BitSource(bytes);
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(100);
|
||||
System.Text.StringBuilder resultTrailer = new System.Text.StringBuilder(0);
|
||||
System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1));
|
||||
int mode = ASCII_ENCODE;
|
||||
do
|
||||
{
|
||||
if (mode == ASCII_ENCODE)
|
||||
{
|
||||
mode = decodeAsciiSegment(bits, result, resultTrailer);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
|
||||
case C40_ENCODE:
|
||||
decodeC40Segment(bits, result);
|
||||
break;
|
||||
|
||||
case TEXT_ENCODE:
|
||||
decodeTextSegment(bits, result);
|
||||
break;
|
||||
|
||||
case ANSIX12_ENCODE:
|
||||
decodeAnsiX12Segment(bits, result);
|
||||
break;
|
||||
|
||||
case EDIFACT_ENCODE:
|
||||
decodeEdifactSegment(bits, result);
|
||||
break;
|
||||
|
||||
case BASE256_ENCODE:
|
||||
decodeBase256Segment(bits, result, byteSegments);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ReaderException.Instance;
|
||||
|
||||
}
|
||||
mode = ASCII_ENCODE;
|
||||
}
|
||||
}
|
||||
while (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>
|
||||
private static int decodeAsciiSegment(BitSource bits, System.Text.StringBuilder result, System.Text.StringBuilder resultTrailer)
|
||||
{
|
||||
bool upperShift = false;
|
||||
do
|
||||
{
|
||||
int oneByte = bits.readBits(8);
|
||||
if (oneByte == 0)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
else if (oneByte <= 128)
|
||||
{
|
||||
// ASCII data (ASCII value + 1)
|
||||
oneByte = upperShift?(oneByte + 128):oneByte;
|
||||
upperShift = false;
|
||||
result.Append((char) (oneByte - 1));
|
||||
return ASCII_ENCODE;
|
||||
}
|
||||
else if (oneByte == 129)
|
||||
{
|
||||
// Pad
|
||||
return PAD_ENCODE;
|
||||
}
|
||||
else if (oneByte <= 229)
|
||||
{
|
||||
// 2-digit data 00-99 (Numeric Value + 130)
|
||||
int value_Renamed = oneByte - 130;
|
||||
if (value_Renamed < 10)
|
||||
{
|
||||
// padd with '0' for single digit values
|
||||
result.Append('0');
|
||||
}
|
||||
result.Append(value_Renamed);
|
||||
}
|
||||
else if (oneByte == 230)
|
||||
{
|
||||
// Latch to C40 encodation
|
||||
return C40_ENCODE;
|
||||
}
|
||||
else if (oneByte == 231)
|
||||
{
|
||||
// Latch to Base 256 encodation
|
||||
return BASE256_ENCODE;
|
||||
}
|
||||
else if (oneByte == 232)
|
||||
{
|
||||
// FNC1
|
||||
//throw ReaderException.getInstance();
|
||||
// Ignore this symbol for now
|
||||
}
|
||||
else if (oneByte == 233)
|
||||
{
|
||||
// Structured Append
|
||||
//throw ReaderException.getInstance();
|
||||
// Ignore this symbol for now
|
||||
}
|
||||
else if (oneByte == 234)
|
||||
{
|
||||
// Reader Programming
|
||||
//throw ReaderException.getInstance();
|
||||
// Ignore this symbol for now
|
||||
}
|
||||
else if (oneByte == 235)
|
||||
{
|
||||
// Upper Shift (shift to Extended ASCII)
|
||||
upperShift = true;
|
||||
}
|
||||
else if (oneByte == 236)
|
||||
{
|
||||
// 05 Macro
|
||||
result.Append("[)>\u001E05\u001D");
|
||||
resultTrailer.Insert(0, "\u001E\u0004");
|
||||
}
|
||||
else if (oneByte == 237)
|
||||
{
|
||||
// 06 Macro
|
||||
result.Append("[)>\u001E06\u001D");
|
||||
resultTrailer.Insert(0, "\u001E\u0004");
|
||||
}
|
||||
else if (oneByte == 238)
|
||||
{
|
||||
// Latch to ANSI X12 encodation
|
||||
return ANSIX12_ENCODE;
|
||||
}
|
||||
else if (oneByte == 239)
|
||||
{
|
||||
// Latch to Text encodation
|
||||
return TEXT_ENCODE;
|
||||
}
|
||||
else if (oneByte == 240)
|
||||
{
|
||||
// Latch to EDIFACT encodation
|
||||
return EDIFACT_ENCODE;
|
||||
}
|
||||
else if (oneByte == 241)
|
||||
{
|
||||
// ECI Character
|
||||
// TODO(bbrown): I think we need to support ECI
|
||||
//throw ReaderException.getInstance();
|
||||
// Ignore this symbol for now
|
||||
}
|
||||
else if (oneByte >= 242)
|
||||
{
|
||||
// Not to be used in ASCII encodation
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
while (bits.available() > 0);
|
||||
return ASCII_ENCODE;
|
||||
}
|
||||
|
||||
/// <summary> See ISO 16022:2006, 5.2.5 and Annex C, Table C.1</summary>
|
||||
private static void decodeC40Segment(BitSource bits, System.Text.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];
|
||||
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);
|
||||
|
||||
int shift = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int cValue = cValues[i];
|
||||
switch (shift)
|
||||
{
|
||||
|
||||
case 0:
|
||||
if (cValue < 3)
|
||||
{
|
||||
shift = cValue + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (upperShift)
|
||||
{
|
||||
result.Append((char) (C40_BASIC_SET_CHARS[cValue] + 128));
|
||||
upperShift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(C40_BASIC_SET_CHARS[cValue]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (upperShift)
|
||||
{
|
||||
result.Append((char) (cValue + 128));
|
||||
upperShift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(cValue);
|
||||
}
|
||||
shift = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (cValue < 27)
|
||||
{
|
||||
if (upperShift)
|
||||
{
|
||||
result.Append((char) (C40_SHIFT2_SET_CHARS[cValue] + 128));
|
||||
upperShift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(C40_SHIFT2_SET_CHARS[cValue]);
|
||||
}
|
||||
}
|
||||
else if (cValue == 27)
|
||||
{
|
||||
// FNC1
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
else if (cValue == 30)
|
||||
{
|
||||
// Upper Shift
|
||||
upperShift = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
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 ReaderException.Instance;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
while (bits.available() > 0);
|
||||
}
|
||||
|
||||
/// <summary> See ISO 16022:2006, 5.2.6 and Annex C, Table C.2</summary>
|
||||
private static void decodeTextSegment(BitSource bits, System.Text.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];
|
||||
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);
|
||||
|
||||
int shift = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int cValue = cValues[i];
|
||||
switch (shift)
|
||||
{
|
||||
|
||||
case 0:
|
||||
if (cValue < 3)
|
||||
{
|
||||
shift = cValue + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (upperShift)
|
||||
{
|
||||
result.Append((char) (TEXT_BASIC_SET_CHARS[cValue] + 128));
|
||||
upperShift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(TEXT_BASIC_SET_CHARS[cValue]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (upperShift)
|
||||
{
|
||||
result.Append((char) (cValue + 128));
|
||||
upperShift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(cValue);
|
||||
}
|
||||
shift = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Shift 2 for Text is the same encoding as C40
|
||||
if (cValue < 27)
|
||||
{
|
||||
if (upperShift)
|
||||
{
|
||||
result.Append((char) (C40_SHIFT2_SET_CHARS[cValue] + 128));
|
||||
upperShift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(C40_SHIFT2_SET_CHARS[cValue]);
|
||||
}
|
||||
}
|
||||
else if (cValue == 27)
|
||||
{
|
||||
// FNC1
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
else if (cValue == 30)
|
||||
{
|
||||
// Upper Shift
|
||||
upperShift = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
shift = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (upperShift)
|
||||
{
|
||||
result.Append((char) (TEXT_SHIFT3_SET_CHARS[cValue] + 128));
|
||||
upperShift = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(TEXT_SHIFT3_SET_CHARS[cValue]);
|
||||
}
|
||||
shift = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ReaderException.Instance;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
while (bits.available() > 0);
|
||||
}
|
||||
|
||||
/// <summary> See ISO 16022:2006, 5.2.7</summary>
|
||||
private static void decodeAnsiX12Segment(BitSource bits, System.Text.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');
|
||||
}
|
||||
else if (cValue == 1)
|
||||
{
|
||||
// X12 segment separator *
|
||||
result.Append('*');
|
||||
}
|
||||
else if (cValue == 2)
|
||||
{
|
||||
// X12 sub-element separator >
|
||||
result.Append('>');
|
||||
}
|
||||
else if (cValue == 3)
|
||||
{
|
||||
// space
|
||||
result.Append(' ');
|
||||
}
|
||||
else if (cValue < 14)
|
||||
{
|
||||
// 0 - 9
|
||||
result.Append((char) (cValue + 44));
|
||||
}
|
||||
else if (cValue < 40)
|
||||
{
|
||||
// A - Z
|
||||
result.Append((char) (cValue + 51));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
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, System.Text.StringBuilder result)
|
||||
{
|
||||
bool unlatch = false;
|
||||
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 == 0x2B67)
|
||||
{
|
||||
// 011111
|
||||
unlatch = true;
|
||||
// If we encounter the unlatch code then continue reading because the Codeword triple
|
||||
// is padded with 0's
|
||||
}
|
||||
|
||||
if (!unlatch)
|
||||
{
|
||||
if ((edifactValue & 32) == 0)
|
||||
{
|
||||
// no 1 in the leading (6th) bit
|
||||
edifactValue |= 64; // Add a leading 01 to the 6 bit binary value
|
||||
}
|
||||
result.Append(edifactValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!unlatch && bits.available() > 0);
|
||||
}
|
||||
|
||||
/// <summary> See ISO 16022:2006, 5.2.9 and Annex B, B.2</summary>
|
||||
private static void decodeBase256Segment(BitSource bits, System.Text.StringBuilder result, System.Collections.ArrayList byteSegments)
|
||||
{
|
||||
// Figure out how long the Base 256 Segment is.
|
||||
int d1 = bits.readBits(8);
|
||||
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) + bits.readBits(8);
|
||||
}
|
||||
sbyte[] bytes = new sbyte[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
bytes[i] = unrandomize255State(bits.readBits(8), i);
|
||||
}
|
||||
byteSegments.Add(SupportClass.ToByteArray(bytes));
|
||||
try
|
||||
{
|
||||
//UPGRADE_TODO: The differences in the Format of parameters for constructor 'java.lang.String.String' may cause compilation errors. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1092'"
|
||||
result.Append(System.Text.Encoding.GetEncoding("ISO8859_1").GetString(SupportClass.ToByteArray(bytes)));
|
||||
}
|
||||
catch (System.IO.IOException uee)
|
||||
{
|
||||
//UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Throwable.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
|
||||
throw new System.SystemException("Platform does not support required encoding: " + uee);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> See ISO 16022:2006, Annex B, B.2</summary>
|
||||
private static sbyte unrandomize255State(int randomizedBase256Codeword, int base256CodewordPosition)
|
||||
{
|
||||
int pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;
|
||||
int tempVariable = randomizedBase256Codeword - pseudoRandomNumber;
|
||||
return (sbyte) (tempVariable >= 0?tempVariable:(tempVariable + 256));
|
||||
}
|
||||
}
|
||||
}
|
153
csharp/datamatrix/decoder/Decoder.cs
Executable file
153
csharp/datamatrix/decoder/Decoder.cs
Executable file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
using BitMatrix = com.google.zxing.common.BitMatrix;
|
||||
using DecoderResult = com.google.zxing.common.DecoderResult;
|
||||
using GF256 = com.google.zxing.common.reedsolomon.GF256;
|
||||
using ReedSolomonDecoder = com.google.zxing.common.reedsolomon.ReedSolomonDecoder;
|
||||
using ReedSolomonException = com.google.zxing.common.reedsolomon.ReedSolomonException;
|
||||
namespace com.google.zxing.datamatrix.decoder
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> bbrown@google.com (Brian Brown)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class Decoder
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'rsDecoder '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ReedSolomonDecoder rsDecoder;
|
||||
|
||||
public Decoder()
|
||||
{
|
||||
rsDecoder = new ReedSolomonDecoder(GF256.DATA_MATRIX_FIELD);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException if the Data Matrix Code cannot be decoded </throws>
|
||||
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_Renamed(j, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return decode(bits);
|
||||
}
|
||||
|
||||
/// <summary> <p>Decodes a Data Matrix Code represented as a {@link 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>
|
||||
/// <throws> ReaderException if the Data Matrix Code cannot be decoded </throws>
|
||||
public DecoderResult decode(BitMatrix bits)
|
||||
{
|
||||
|
||||
// Construct a parser and read version, error-correction level
|
||||
BitMatrixParser parser = new BitMatrixParser(bits);
|
||||
Version version = parser.readVersion(bits);
|
||||
|
||||
// Read codewords
|
||||
sbyte[] codewords = parser.readCodewords();
|
||||
// Separate into data blocks
|
||||
DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version);
|
||||
|
||||
// Count total number of data bytes
|
||||
int totalBytes = 0;
|
||||
for (int i = 0; i < dataBlocks.Length; i++)
|
||||
{
|
||||
totalBytes += dataBlocks[i].NumDataCodewords;
|
||||
}
|
||||
sbyte[] resultBytes = new sbyte[totalBytes];
|
||||
int resultOffset = 0;
|
||||
|
||||
// Error-correct and copy data blocks together into a stream of bytes
|
||||
for (int j = 0; j < dataBlocks.Length; j++)
|
||||
{
|
||||
DataBlock dataBlock = dataBlocks[j];
|
||||
sbyte[] codewordBytes = dataBlock.Codewords;
|
||||
int numDataCodewords = dataBlock.NumDataCodewords;
|
||||
correctErrors(codewordBytes, numDataCodewords);
|
||||
for (int i = 0; i < numDataCodewords; i++)
|
||||
{
|
||||
resultBytes[resultOffset++] = 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>
|
||||
/// <throws> ReaderException if error correction fails </throws>
|
||||
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 ReaderException.Instance;
|
||||
}
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
241
csharp/datamatrix/decoder/Version.cs
Executable file
241
csharp/datamatrix/decoder/Version.cs
Executable file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
namespace com.google.zxing.datamatrix.decoder
|
||||
{
|
||||
|
||||
/// <summary> The Version object encapsulates attributes about a particular
|
||||
/// size Data Matrix Code.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> bbrown@google.com (Brian Brown)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class Version
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'VERSIONS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly Version[] VERSIONS = buildVersions();
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'versionNumber '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int versionNumber;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'symbolSizeRows '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int symbolSizeRows;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'symbolSizeColumns '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int symbolSizeColumns;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'dataRegionSizeRows '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int dataRegionSizeRows;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'dataRegionSizeColumns '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int dataRegionSizeColumns;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ecBlocks '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ECBlocks ecBlocks;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'totalCodewords '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private 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.getECBlocks();
|
||||
for (int i = 0; i < ecbArray.Length; i++)
|
||||
{
|
||||
ECB ecBlock = ecbArray[i];
|
||||
total += ecBlock.Count * (ecBlock.DataCodewords + ecCodewords);
|
||||
}
|
||||
this.totalCodewords = total;
|
||||
}
|
||||
|
||||
internal ECBlocks getECBlocks()
|
||||
{
|
||||
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> {@link Version} for a Data Matrix Code of those dimensions
|
||||
/// </returns>
|
||||
/// <throws> ReaderException if dimensions do correspond to a valid Data Matrix size </throws>
|
||||
public static Version getVersionForDimensions(int numRows, int numColumns)
|
||||
{
|
||||
if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
// TODO(bbrown): This is doing a linear search through the array of versions.
|
||||
// If we interleave the rectangular versions with the square versions we could
|
||||
// do a binary search.
|
||||
int numVersions = VERSIONS.Length;
|
||||
for (int i = 0; i < numVersions; ++i)
|
||||
{
|
||||
Version version = VERSIONS[i];
|
||||
if (version.symbolSizeRows == numRows && version.symbolSizeColumns == numColumns)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
/// <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
|
||||
{
|
||||
internal int ECCodewords
|
||||
{
|
||||
get
|
||||
{
|
||||
return ecCodewords;
|
||||
}
|
||||
|
||||
}
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ecCodewords '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int ecCodewords;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ecBlocks '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private 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 ECB[] getECBlocks()
|
||||
{
|
||||
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
|
||||
{
|
||||
internal int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
internal int DataCodewords
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataCodewords;
|
||||
}
|
||||
|
||||
}
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'count '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int count;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'dataCodewords '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int dataCodewords;
|
||||
|
||||
internal ECB(int count, int dataCodewords)
|
||||
{
|
||||
this.count = count;
|
||||
this.dataCodewords = dataCodewords;
|
||||
}
|
||||
}
|
||||
|
||||
public override System.String ToString()
|
||||
{
|
||||
return System.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, 10, 16, new ECBlocks(24, new ECB(1, 32))), new Version(30, 16, 48, 14, 22, new ECBlocks(28,
|
||||
new ECB(1, 49)))};
|
||||
}
|
||||
}
|
||||
}
|
325
csharp/datamatrix/detector/Detector.cs
Executable file
325
csharp/datamatrix/detector/Detector.cs
Executable file
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
using BitMatrix = com.google.zxing.common.BitMatrix;
|
||||
using Collections = com.google.zxing.common.Collections;
|
||||
using Comparator = com.google.zxing.common.Comparator;
|
||||
using DetectorResult = com.google.zxing.common.DetectorResult;
|
||||
using GridSampler = com.google.zxing.common.GridSampler;
|
||||
using MonochromeRectangleDetector = com.google.zxing.common.detector.MonochromeRectangleDetector;
|
||||
namespace com.google.zxing.datamatrix.detector
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class Detector
|
||||
{
|
||||
|
||||
//private static final int MAX_MODULES = 32;
|
||||
|
||||
// Trick to avoid creating new Integer objects below -- a sort of crude copy of
|
||||
// the Integer.valueOf(int) optimization added in Java 5, not in J2ME
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'INTEGERS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly System.Int32[] INTEGERS = new System.Int32[]{0, 1, 2, 3, 4};
|
||||
// No, can't use valueOf()
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'image '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private BitMatrix image;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'rectangleDetector '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private MonochromeRectangleDetector rectangleDetector;
|
||||
|
||||
public Detector(BitMatrix image)
|
||||
{
|
||||
this.image = image;
|
||||
rectangleDetector = new MonochromeRectangleDetector(image);
|
||||
}
|
||||
|
||||
/// <summary> <p>Detects a Data Matrix Code in an image.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns> {@link DetectorResult} encapsulating results of detecting a QR Code
|
||||
/// </returns>
|
||||
/// <throws> ReaderException if no Data Matrix Code can be found </throws>
|
||||
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
|
||||
System.Collections.ArrayList transitions = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(4));
|
||||
transitions.Add(transitionsBetween(pointA, pointB));
|
||||
transitions.Add(transitionsBetween(pointA, pointC));
|
||||
transitions.Add(transitionsBetween(pointB, pointD));
|
||||
transitions.Add(transitionsBetween(pointC, pointD));
|
||||
Collections.insertionSort(transitions, 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 = (ResultPointsAndTransitions) transitions[0];
|
||||
ResultPointsAndTransitions lSideTwo = (ResultPointsAndTransitions) 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.
|
||||
System.Collections.Hashtable pointCount = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
|
||||
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;
|
||||
System.Collections.IEnumerator points = pointCount.Keys.GetEnumerator();
|
||||
//UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
|
||||
while (points.MoveNext())
|
||||
{
|
||||
//UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
|
||||
ResultPoint point = (ResultPoint) points.Current;
|
||||
System.Int32 value_Renamed = (System.Int32) pointCount[point];
|
||||
if (value_Renamed == 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 ReaderException.Instance;
|
||||
}
|
||||
|
||||
// Bottom left is correct but top left and bottom right might be switched
|
||||
ResultPoint[] corners = new ResultPoint[]{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. The number of transitions could be higher than it should be
|
||||
// due to noise. So we try both and take the min.
|
||||
|
||||
int dimension = System.Math.Min(transitionsBetween(topLeft, topRight).Transitions, transitionsBetween(bottomRight, topRight).Transitions);
|
||||
if ((dimension & 0x01) == 1)
|
||||
{
|
||||
// it can't be odd, so, round... up?
|
||||
dimension++;
|
||||
}
|
||||
dimension += 2;
|
||||
|
||||
BitMatrix bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, dimension);
|
||||
return new DetectorResult(bits, new ResultPoint[]{pointA, pointB, pointC, pointD});
|
||||
}
|
||||
|
||||
/// <summary> Increments the Integer associated with a key by one.</summary>
|
||||
private static void increment(System.Collections.Hashtable table, ResultPoint key)
|
||||
{
|
||||
//System.Int32 value_Renamed = (System.Int32) table[key];
|
||||
////UPGRADE_TODO: The 'System.Int32' structure does not have an equivalent to NULL. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1291'"
|
||||
//table[key] = value_Renamed == null?INTEGERS[1]:INTEGERS[value_Renamed + 1];
|
||||
// Redivivus.in Java to c# Porting update
|
||||
// 30/01/2010
|
||||
// Added
|
||||
// START
|
||||
System.Int32 value_Renamed = 0;
|
||||
try
|
||||
{
|
||||
if (table.Count > 0)
|
||||
value_Renamed = (System.Int32)table[key];
|
||||
}
|
||||
catch
|
||||
{
|
||||
value_Renamed = 0;
|
||||
}
|
||||
table[key] = value_Renamed == 0 ? INTEGERS[1] : INTEGERS[value_Renamed + 1];
|
||||
//END
|
||||
}
|
||||
|
||||
private static BitMatrix sampleGrid(BitMatrix image, ResultPoint topLeft, ResultPoint bottomLeft, ResultPoint bottomRight, int dimension)
|
||||
{
|
||||
|
||||
// We make up the top right point for now, based on the others.
|
||||
// TODO: we actually found a fourth corner above and figured out which of two modules
|
||||
// it was the corner of. We could use that here and adjust for perspective distortion.
|
||||
float topRightX = (bottomRight.X - bottomLeft.X) + topLeft.X;
|
||||
float topRightY = (bottomRight.Y - bottomLeft.Y) + topLeft.Y;
|
||||
|
||||
// Note that unlike in the QR Code sampler, we didn't find the center of modules, but the
|
||||
// very corners. So there is no 0.5f here; 0.0f is right.
|
||||
GridSampler sampler = GridSampler.Instance;
|
||||
return sampler.sampleGrid(image, dimension, 0.0f, 0.0f, dimension, 0.0f, dimension, dimension, 0.0f, dimension, topLeft.X, topLeft.Y, topRightX, topRightY, 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()
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int fromX = (int) from.X;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int fromY = (int) from.Y;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int toX = (int) to.X;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
int toY = (int) to.Y;
|
||||
bool steep = System.Math.Abs(toY - fromY) > System.Math.Abs(toX - fromX);
|
||||
if (steep)
|
||||
{
|
||||
int temp = fromX;
|
||||
fromX = fromY;
|
||||
fromY = temp;
|
||||
temp = toX;
|
||||
toX = toY;
|
||||
toY = temp;
|
||||
}
|
||||
|
||||
int dx = System.Math.Abs(toX - fromX);
|
||||
int dy = System.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_Renamed(steep?fromY:fromX, steep?fromX:fromY);
|
||||
for (int x = fromX, y = fromY; x != toX; x += xstep)
|
||||
{
|
||||
bool isBlack = image.get_Renamed(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 class ResultPointsAndTransitions
|
||||
{
|
||||
public ResultPoint From
|
||||
{
|
||||
get
|
||||
{
|
||||
return from;
|
||||
}
|
||||
|
||||
}
|
||||
public ResultPoint To
|
||||
{
|
||||
get
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
||||
}
|
||||
public int Transitions
|
||||
{
|
||||
get
|
||||
{
|
||||
return transitions;
|
||||
}
|
||||
|
||||
}
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'from '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ResultPoint from;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'to '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private ResultPoint to;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'transitions '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int transitions;
|
||||
internal ResultPointsAndTransitions(ResultPoint from, ResultPoint to, int transitions)
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.transitions = transitions;
|
||||
}
|
||||
public override System.String ToString()
|
||||
{
|
||||
return from + "/" + to + '/' + transitions;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Orders ResultPointsAndTransitions by number of transitions, ascending.</summary>
|
||||
private class ResultPointsAndTransitionsComparator : Comparator
|
||||
{
|
||||
public int compare(System.Object o1, System.Object o2)
|
||||
{
|
||||
return ((ResultPointsAndTransitions) o1).Transitions - ((ResultPointsAndTransitions) o2).Transitions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
103
csharp/multi/ByQuadrantReader.cs
Executable file
103
csharp/multi/ByQuadrantReader.cs
Executable file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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 BinaryBitmap = com.google.zxing.BinaryBitmap;
|
||||
using Reader = com.google.zxing.Reader;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
namespace com.google.zxing.multi
|
||||
{
|
||||
|
||||
/// <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 : Reader
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'delegate '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private Reader delegate_Renamed;
|
||||
|
||||
public ByQuadrantReader(Reader delegate_Renamed)
|
||||
{
|
||||
this.delegate_Renamed = delegate_Renamed;
|
||||
}
|
||||
|
||||
public Result decode(BinaryBitmap image)
|
||||
{
|
||||
return decode(image, null);
|
||||
}
|
||||
|
||||
public Result decode(BinaryBitmap image, System.Collections.Hashtable 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_Renamed.decode(topLeft, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
|
||||
BinaryBitmap topRight = image.crop(halfWidth, 0, halfWidth, halfHeight);
|
||||
try
|
||||
{
|
||||
return delegate_Renamed.decode(topRight, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
|
||||
BinaryBitmap bottomLeft = image.crop(0, halfHeight, halfWidth, halfHeight);
|
||||
try
|
||||
{
|
||||
return delegate_Renamed.decode(bottomLeft, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
|
||||
BinaryBitmap bottomRight = image.crop(halfWidth, halfHeight, halfWidth, halfHeight);
|
||||
try
|
||||
{
|
||||
return delegate_Renamed.decode(bottomRight, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
|
||||
int quarterWidth = halfWidth / 2;
|
||||
int quarterHeight = halfHeight / 2;
|
||||
BinaryBitmap center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
|
||||
return delegate_Renamed.decode(center, hints);
|
||||
}
|
||||
}
|
||||
}
|
175
csharp/multi/GenericMultipleBarcodeReader.cs
Executable file
175
csharp/multi/GenericMultipleBarcodeReader.cs
Executable file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* 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 Reader = com.google.zxing.Reader;
|
||||
using Result = com.google.zxing.Result;
|
||||
using BinaryBitmap = com.google.zxing.BinaryBitmap;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
namespace com.google.zxing.multi
|
||||
{
|
||||
|
||||
/// <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
|
||||
/// {@link com.google.zxing.ResultPoint}s are scanned, recursively.</p>
|
||||
///
|
||||
/// <p>A caller may want to also employ {@link 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 {@link Reader} a caller might pass
|
||||
/// <code>new ByQuadrantReader(reader)</code>.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class GenericMultipleBarcodeReader : MultipleBarcodeReader
|
||||
{
|
||||
|
||||
private const int MIN_DIMENSION_TO_RECUR = 30;
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'delegate '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private Reader delegate_Renamed;
|
||||
|
||||
public GenericMultipleBarcodeReader(Reader delegate_Renamed)
|
||||
{
|
||||
this.delegate_Renamed = delegate_Renamed;
|
||||
}
|
||||
|
||||
public Result[] decodeMultiple(BinaryBitmap image)
|
||||
{
|
||||
return decodeMultiple(image, null);
|
||||
}
|
||||
|
||||
public Result[] decodeMultiple(BinaryBitmap image, System.Collections.Hashtable hints)
|
||||
{
|
||||
System.Collections.ArrayList results = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
doDecodeMultiple(image, hints, results, 0, 0);
|
||||
if ((results.Count == 0))
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
int numResults = results.Count;
|
||||
Result[] resultArray = new Result[numResults];
|
||||
for (int i = 0; i < numResults; i++)
|
||||
{
|
||||
resultArray[i] = (Result) results[i];
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
private void doDecodeMultiple(BinaryBitmap image, System.Collections.Hashtable hints, System.Collections.ArrayList results, int xOffset, int yOffset)
|
||||
{
|
||||
Result result;
|
||||
try
|
||||
{
|
||||
result = delegate_Renamed.decode(image, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
bool alreadyFound = false;
|
||||
for (int i = 0; i < results.Count; i++)
|
||||
{
|
||||
Result existingResult = (Result) results[i];
|
||||
if (existingResult.Text.Equals(result.Text))
|
||||
{
|
||||
alreadyFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alreadyFound)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
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;
|
||||
for (int i = 0; i < resultPoints.Length; i++)
|
||||
{
|
||||
ResultPoint point = resultPoints[i];
|
||||
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)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
doDecodeMultiple(image.crop(0, 0, (int) minX, height), hints, results, xOffset, yOffset);
|
||||
}
|
||||
// Decode above barcode
|
||||
if (minY > MIN_DIMENSION_TO_RECUR)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
doDecodeMultiple(image.crop(0, 0, width, (int) minY), hints, results, xOffset, yOffset);
|
||||
}
|
||||
// Decode right of barcode
|
||||
if (maxX < width - MIN_DIMENSION_TO_RECUR)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
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)
|
||||
{
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
40
csharp/multi/MultipleBarcodeReader.cs
Executable file
40
csharp/multi/MultipleBarcodeReader.cs
Executable file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 Result = com.google.zxing.Result;
|
||||
using BinaryBitmap = com.google.zxing.BinaryBitmap;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
namespace com.google.zxing.multi
|
||||
{
|
||||
|
||||
/// <summary> Implementation of this interface attempt to read several barcodes from one image.
|
||||
///
|
||||
/// </summary>
|
||||
/// <seealso cref="com.google.zxing.Reader">
|
||||
/// </seealso>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public interface MultipleBarcodeReader
|
||||
{
|
||||
|
||||
Result[] decodeMultiple(BinaryBitmap image);
|
||||
|
||||
Result[] decodeMultiple(BinaryBitmap image, System.Collections.Hashtable hints);
|
||||
}
|
||||
}
|
93
csharp/multi/qrcode/QRCodeMultiReader.cs
Executable file
93
csharp/multi/qrcode/QRCodeMultiReader.cs
Executable file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using BinaryBitmap = com.google.zxing.BinaryBitmap;
|
||||
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;
|
||||
namespace com.google.zxing.multi.qrcode
|
||||
{
|
||||
|
||||
/// <summary> This implementation can detect and decode multiple QR Codes in an image.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> Hannes Erven
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class QRCodeMultiReader:QRCodeReader, MultipleBarcodeReader
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'EMPTY_RESULT_ARRAY '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly Result[] EMPTY_RESULT_ARRAY = new Result[0];
|
||||
|
||||
public Result[] decodeMultiple(BinaryBitmap image)
|
||||
{
|
||||
return decodeMultiple(image, null);
|
||||
}
|
||||
|
||||
public Result[] decodeMultiple(BinaryBitmap image, System.Collections.Hashtable hints)
|
||||
{
|
||||
System.Collections.ArrayList results = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
DetectorResult[] detectorResult = new MultiDetector(image.BlackMatrix).detectMulti(hints);
|
||||
for (int i = 0; i < detectorResult.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
DecoderResult decoderResult = Decoder.decode(detectorResult[i].Bits);
|
||||
ResultPoint[] points = detectorResult[i].Points;
|
||||
Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE);
|
||||
if (decoderResult.ByteSegments != null)
|
||||
{
|
||||
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.ByteSegments);
|
||||
}
|
||||
if (decoderResult.ECLevel != null)
|
||||
{
|
||||
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel.ToString());
|
||||
}
|
||||
results.Add(result);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
// ignore and continue
|
||||
}
|
||||
}
|
||||
if ((results.Count == 0))
|
||||
{
|
||||
return EMPTY_RESULT_ARRAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result[] resultArray = new Result[results.Count];
|
||||
for (int i = 0; i < results.Count; i++)
|
||||
{
|
||||
resultArray[i] = (Result) results[i];
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
csharp/multi/qrcode/detector/MultiDetector.cs
Executable file
84
csharp/multi/qrcode/detector/MultiDetector.cs
Executable file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 ReaderException = com.google.zxing.ReaderException;
|
||||
using DetectorResult = com.google.zxing.common.DetectorResult;
|
||||
using BitMatrix = com.google.zxing.common.BitMatrix;
|
||||
using Detector = com.google.zxing.qrcode.detector.Detector;
|
||||
using FinderPatternInfo = com.google.zxing.qrcode.detector.FinderPatternInfo;
|
||||
namespace com.google.zxing.multi.qrcode.detector
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> Hannes Erven
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
public sealed class MultiDetector:Detector
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'EMPTY_DETECTOR_RESULTS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly DetectorResult[] EMPTY_DETECTOR_RESULTS = new DetectorResult[0];
|
||||
|
||||
public MultiDetector(BitMatrix image):base(image)
|
||||
{
|
||||
}
|
||||
|
||||
public DetectorResult[] detectMulti(System.Collections.Hashtable hints)
|
||||
{
|
||||
BitMatrix image = Image;
|
||||
MultiFinderPatternFinder finder = new MultiFinderPatternFinder(image);
|
||||
FinderPatternInfo[] info = finder.findMulti(hints);
|
||||
|
||||
if (info == null || info.Length == 0)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
System.Collections.ArrayList result = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
for (int i = 0; i < info.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
result.Add(processFinderPatternInfo(info[i]));
|
||||
}
|
||||
catch (ReaderException e)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if ((result.Count == 0))
|
||||
{
|
||||
return EMPTY_DETECTOR_RESULTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DetectorResult[] resultArray = new DetectorResult[result.Count];
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
resultArray[i] = (DetectorResult) result[i];
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
367
csharp/multi/qrcode/detector/MultiFinderPatternFinder.cs
Executable file
367
csharp/multi/qrcode/detector/MultiFinderPatternFinder.cs
Executable file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* 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 DecodeHintType = com.google.zxing.DecodeHintType;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
using ResultPointCallback = com.google.zxing.ResultPointCallback;
|
||||
using Collections = com.google.zxing.common.Collections;
|
||||
using Comparator = com.google.zxing.common.Comparator;
|
||||
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;
|
||||
namespace com.google.zxing.multi.qrcode.detector
|
||||
{
|
||||
|
||||
/// <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 {@link 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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> Hannes Erven
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
|
||||
|
||||
sealed class MultiFinderPatternFinder:FinderPatternFinder
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'EMPTY_RESULT_ARRAY '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
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>
|
||||
private class ModuleSizeComparator : Comparator
|
||||
{
|
||||
public int compare(System.Object center1, System.Object center2)
|
||||
{
|
||||
float value_Renamed = ((FinderPattern) center2).EstimatedModuleSize - ((FinderPattern) center1).EstimatedModuleSize;
|
||||
return value_Renamed < 0.0?- 1:(value_Renamed > 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 {@link FinderPattern}s from our list of candidates. The "best" are
|
||||
/// those that have been detected at least {@link #CENTER_QUORUM} times, and whose module
|
||||
/// size differs from the average among those patterns the least
|
||||
/// </returns>
|
||||
/// <throws> ReaderException if 3 such finder patterns do not exist </throws>
|
||||
private FinderPattern[][] selectBestPatterns()
|
||||
{
|
||||
System.Collections.ArrayList possibleCenters = PossibleCenters;
|
||||
int size = possibleCenters.Count;
|
||||
|
||||
if (size < 3)
|
||||
{
|
||||
// Couldn't find enough finder patterns
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin HE modifications to safely detect multiple codes of equal size
|
||||
*/
|
||||
if (size == 3)
|
||||
{
|
||||
return new FinderPattern[][]{new FinderPattern[]{(FinderPattern) possibleCenters[0], (FinderPattern) possibleCenters[1], (FinderPattern) possibleCenters[2]}};
|
||||
}
|
||||
|
||||
// Sort by estimated module size to speed up the upcoming checks
|
||||
Collections.insertionSort(possibleCenters, 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.
|
||||
*/
|
||||
|
||||
System.Collections.ArrayList results = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); // holder for the results
|
||||
|
||||
for (int i1 = 0; i1 < (size - 2); i1++)
|
||||
{
|
||||
FinderPattern p1 = (FinderPattern) possibleCenters[i1];
|
||||
if (p1 == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i2 = i1 + 1; i2 < (size - 1); i2++)
|
||||
{
|
||||
FinderPattern p2 = (FinderPattern) possibleCenters[i2];
|
||||
if (p2 == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare the expected module sizes; if they are really off, skip
|
||||
float vModSize12 = (p1.EstimatedModuleSize - p2.EstimatedModuleSize) / (System.Math.Min(p1.EstimatedModuleSize, p2.EstimatedModuleSize));
|
||||
float vModSize12A = System.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 = (FinderPattern) possibleCenters[i3];
|
||||
if (p3 == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare the expected module sizes; if they are really off, skip
|
||||
float vModSize23 = (p2.EstimatedModuleSize - p3.EstimatedModuleSize) / (System.Math.Min(p2.EstimatedModuleSize, p3.EstimatedModuleSize));
|
||||
float vModSize23A = System.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 = new FinderPattern[]{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;
|
||||
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 = System.Math.Abs(((dA - dB) / System.Math.Min(dA, dB)));
|
||||
if (vABBC >= 0.1f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate the diagonal length by assuming a 90° angle at topleft
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
float dCpy = (float) System.Math.Sqrt(dA * dA + dB * dB);
|
||||
// Compare to the real distance in %
|
||||
float vPyC = System.Math.Abs(((dC - dCpy) / System.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))
|
||||
{
|
||||
FinderPattern[][] resultArray = new FinderPattern[results.Count][];
|
||||
for (int i = 0; i < results.Count; i++)
|
||||
{
|
||||
resultArray[i] = (FinderPattern[]) results[i];
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
// Nothing found!
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
public FinderPatternInfo[] findMulti(System.Collections.Hashtable 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.
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
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_Renamed(j, i))
|
||||
{
|
||||
// Black pixel
|
||||
if ((currentState & 1) == 1)
|
||||
{
|
||||
// Counting white pixels
|
||||
currentState++;
|
||||
}
|
||||
stateCount[currentState]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// White pixel
|
||||
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_Renamed(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;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, shift counts back by two
|
||||
stateCount[0] = stateCount[2];
|
||||
stateCount[1] = stateCount[3];
|
||||
stateCount[2] = stateCount[4];
|
||||
stateCount[3] = 1;
|
||||
stateCount[4] = 0;
|
||||
currentState = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stateCount[++currentState]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Counting white pixels
|
||||
stateCount[currentState]++;
|
||||
}
|
||||
}
|
||||
} // for j=...
|
||||
|
||||
if (foundPatternCross(stateCount))
|
||||
{
|
||||
handlePossibleCenter(stateCount, i, maxJ);
|
||||
} // end if foundPatternCross
|
||||
} // for i=iSkip-1 ...
|
||||
FinderPattern[][] patternInfo = selectBestPatterns();
|
||||
System.Collections.ArrayList result = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
for (int i = 0; i < patternInfo.Length; i++)
|
||||
{
|
||||
FinderPattern[] pattern = patternInfo[i];
|
||||
ResultPoint.orderBestPatterns(pattern);
|
||||
result.Add(new FinderPatternInfo(pattern));
|
||||
}
|
||||
|
||||
if ((result.Count == 0))
|
||||
{
|
||||
return EMPTY_RESULT_ARRAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
FinderPatternInfo[] resultArray = new FinderPatternInfo[result.Count];
|
||||
for (int i = 0; i < result.Count; i++)
|
||||
{
|
||||
resultArray[i] = (FinderPatternInfo) result[i];
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
444
csharp/oned/Code128Reader.cs
Executable file
444
csharp/oned/Code128Reader.cs
Executable file
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> <p>Decodes Code 128 barcodes.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class Code128Reader:OneDReader
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'CODE_PATTERNS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int[][] CODE_PATTERNS = new int[][]{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}};
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'MAX_AVG_VARIANCE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
private static readonly int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.25f);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'MAX_INDIVIDUAL_VARIANCE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
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;
|
||||
|
||||
private static int[] findStartPattern(BitArray row)
|
||||
{
|
||||
int width = row.Size;
|
||||
int rowOffset = 0;
|
||||
while (rowOffset < width)
|
||||
{
|
||||
if (row.get_Renamed(rowOffset))
|
||||
{
|
||||
break;
|
||||
}
|
||||
rowOffset++;
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
bool pixel = row.get_Renamed(i);
|
||||
if (pixel ^ 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;
|
||||
}
|
||||
}
|
||||
if (bestMatch >= 0)
|
||||
{
|
||||
// Look for whitespace before start pattern, >= 50% of width of start pattern
|
||||
if (row.isRange(System.Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false))
|
||||
{
|
||||
return new int[]{patternStart, i, bestMatch};
|
||||
}
|
||||
}
|
||||
patternStart += counters[0] + counters[1];
|
||||
for (int y = 2; y < patternLength; y++)
|
||||
{
|
||||
counters[y - 2] = counters[y];
|
||||
}
|
||||
counters[patternLength - 2] = 0;
|
||||
counters[patternLength - 1] = 0;
|
||||
counterPosition--;
|
||||
}
|
||||
else
|
||||
{
|
||||
counterPosition++;
|
||||
}
|
||||
counters[counterPosition] = 1;
|
||||
isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
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 ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable 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 ReaderException.Instance;
|
||||
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
bool isNextShifted = false;
|
||||
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(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);
|
||||
|
||||
// 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;
|
||||
for (int i = 0; i < counters.Length; i++)
|
||||
{
|
||||
nextStart += counters[i];
|
||||
}
|
||||
|
||||
// Take care of illegal start codes
|
||||
switch (code)
|
||||
{
|
||||
|
||||
case CODE_START_A:
|
||||
case CODE_START_B:
|
||||
case CODE_START_C:
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
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_C;
|
||||
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)
|
||||
{
|
||||
switch (codeSet)
|
||||
{
|
||||
|
||||
case CODE_CODE_A:
|
||||
codeSet = CODE_CODE_C;
|
||||
break;
|
||||
|
||||
case CODE_CODE_B:
|
||||
codeSet = CODE_CODE_A;
|
||||
break;
|
||||
|
||||
case CODE_CODE_C:
|
||||
codeSet = CODE_CODE_B;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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:
|
||||
int width = row.Size;
|
||||
while (nextStart < width && row.get_Renamed(nextStart))
|
||||
{
|
||||
nextStart++;
|
||||
}
|
||||
if (!row.isRange(nextStart, System.Math.Min(width, nextStart + (nextStart - lastStart) / 2), false))
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
// Pull out from sum the value of the penultimate check code
|
||||
checksumTotal -= multiplier * lastCode;
|
||||
// lastCode is the checksum then:
|
||||
if (checksumTotal % 103 != lastCode)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
// Need to pull out the check digits from string
|
||||
int resultLength = result.Length;
|
||||
// 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, resultLength - (resultLength - 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Remove(resultLength - 1, resultLength - (resultLength - 1));
|
||||
}
|
||||
}
|
||||
|
||||
System.String resultString = result.ToString();
|
||||
|
||||
if (resultString.Length == 0)
|
||||
{
|
||||
// Almost surely a false positive
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
float left = (float) (startPatternInfo[1] + startPatternInfo[0]) / 2.0f;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
float right = (float) (nextStart + lastStart) / 2.0f;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
return new Result(resultString, null, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_128);
|
||||
}
|
||||
}
|
||||
}
|
392
csharp/oned/Code39Reader.cs
Executable file
392
csharp/oned/Code39Reader.cs
Executable file
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> <p>Decodes Code 39 barcodes. This does not support "Full ASCII Code 39" yet.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class Code39Reader:OneDReader
|
||||
{
|
||||
|
||||
private const System.String ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%";
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ALPHABET '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
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>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'CHARACTER_ENCODINGS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int[] CHARACTER_ENCODINGS = new int[]{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};
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ASTERISK_ENCODING '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int ASTERISK_ENCODING = CHARACTER_ENCODINGS[39];
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'usingCheckDigit '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private bool usingCheckDigit;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'extendedMode '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private bool extendedMode;
|
||||
|
||||
/// <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()
|
||||
{
|
||||
usingCheckDigit = false;
|
||||
extendedMode = 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 = usingCheckDigit;
|
||||
this.extendedMode = 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;
|
||||
}
|
||||
|
||||
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
|
||||
{
|
||||
|
||||
int[] start = findAsteriskPattern(row);
|
||||
int nextStart = start[1];
|
||||
int end = row.Size;
|
||||
|
||||
// Read off white space
|
||||
while (nextStart < end && !row.get_Renamed(nextStart))
|
||||
{
|
||||
nextStart++;
|
||||
}
|
||||
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(20);
|
||||
int[] counters = new int[9];
|
||||
char decodedChar;
|
||||
int lastStart;
|
||||
do
|
||||
{
|
||||
recordPattern(row, nextStart, counters);
|
||||
int pattern = toNarrowWidePattern(counters);
|
||||
if (pattern < 0)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
decodedChar = patternToChar(pattern);
|
||||
result.Append(decodedChar);
|
||||
lastStart = nextStart;
|
||||
for (int i = 0; i < counters.Length; i++)
|
||||
{
|
||||
nextStart += counters[i];
|
||||
}
|
||||
// Read off white space
|
||||
while (nextStart < end && !row.get_Renamed(nextStart))
|
||||
{
|
||||
nextStart++;
|
||||
}
|
||||
}
|
||||
while (decodedChar != '*');
|
||||
result.Remove(result.Length - 1, 1); // remove asterisk
|
||||
|
||||
// Look for whitespace after pattern:
|
||||
int lastPatternSize = 0;
|
||||
for (int i = 0; i < counters.Length; i++)
|
||||
{
|
||||
lastPatternSize += counters[i];
|
||||
}
|
||||
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 / 2 < lastPatternSize)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
if (usingCheckDigit)
|
||||
{
|
||||
int max = result.Length - 1;
|
||||
int total = 0;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
total += ALPHABET_STRING.IndexOf((System.Char) result[i]);
|
||||
}
|
||||
if (total % 43 != ALPHABET_STRING.IndexOf((System.Char) result[max]))
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
result.Remove(max, 1);
|
||||
}
|
||||
|
||||
System.String resultString = result.ToString();
|
||||
if (extendedMode)
|
||||
{
|
||||
resultString = decodeExtended(resultString);
|
||||
}
|
||||
|
||||
if (resultString.Length == 0)
|
||||
{
|
||||
// Almost surely a false positive
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
float left = (float) (start[1] + start[0]) / 2.0f;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
float right = (float) (nextStart + lastStart) / 2.0f;
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
return new Result(resultString, null, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_39);
|
||||
}
|
||||
|
||||
private static int[] findAsteriskPattern(BitArray row)
|
||||
{
|
||||
int width = row.Size;
|
||||
int rowOffset = 0;
|
||||
while (rowOffset < width)
|
||||
{
|
||||
if (row.get_Renamed(rowOffset))
|
||||
{
|
||||
break;
|
||||
}
|
||||
rowOffset++;
|
||||
}
|
||||
|
||||
int counterPosition = 0;
|
||||
int[] counters = new int[9];
|
||||
int patternStart = rowOffset;
|
||||
bool isWhite = false;
|
||||
int patternLength = counters.Length;
|
||||
|
||||
for (int i = rowOffset; i < width; i++)
|
||||
{
|
||||
bool pixel = row.get_Renamed(i);
|
||||
if (pixel ^ isWhite)
|
||||
{
|
||||
counters[counterPosition]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (counterPosition == patternLength - 1)
|
||||
{
|
||||
if (toNarrowWidePattern(counters) == ASTERISK_ENCODING)
|
||||
{
|
||||
// Look for whitespace before start pattern, >= 50% of width of start pattern
|
||||
if (row.isRange(System.Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false))
|
||||
{
|
||||
return new int[]{patternStart, i};
|
||||
}
|
||||
}
|
||||
patternStart += counters[0] + counters[1];
|
||||
for (int y = 2; y < patternLength; y++)
|
||||
{
|
||||
counters[y - 2] = counters[y];
|
||||
}
|
||||
counters[patternLength - 2] = 0;
|
||||
counters[patternLength - 1] = 0;
|
||||
counterPosition--;
|
||||
}
|
||||
else
|
||||
{
|
||||
counterPosition++;
|
||||
}
|
||||
counters[counterPosition] = 1;
|
||||
isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
// 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 = System.Int32.MaxValue;
|
||||
for (int i = 0; i < numCounters; i++)
|
||||
{
|
||||
int counter = counters[i];
|
||||
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 (counters[i] > 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 (counters[i] > 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;
|
||||
}
|
||||
|
||||
private static char patternToChar(int pattern)
|
||||
{
|
||||
for (int i = 0; i < CHARACTER_ENCODINGS.Length; i++)
|
||||
{
|
||||
if (CHARACTER_ENCODINGS[i] == pattern)
|
||||
{
|
||||
return ALPHABET[i];
|
||||
}
|
||||
}
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
private static System.String decodeExtended(System.String encoded)
|
||||
{
|
||||
int length = encoded.Length;
|
||||
System.Text.StringBuilder decoded = new System.Text.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 = '\x0000';
|
||||
switch (c)
|
||||
{
|
||||
|
||||
case '+':
|
||||
// +A to +Z map to a to z
|
||||
if (next >= 'A' && next <= 'Z')
|
||||
{
|
||||
decodedChar = (char) (next + 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
break;
|
||||
|
||||
case '$':
|
||||
// $A to $Z map to control codes SH to SB
|
||||
if (next >= 'A' && next <= 'Z')
|
||||
{
|
||||
decodedChar = (char) (next - 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
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 ReaderException.Instance;
|
||||
}
|
||||
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 ReaderException.Instance;
|
||||
}
|
||||
break;
|
||||
}
|
||||
decoded.Append(decodedChar);
|
||||
// bump up i again since we read two characters
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
decoded.Append(c);
|
||||
}
|
||||
}
|
||||
return decoded.ToString();
|
||||
}
|
||||
}
|
||||
}
|
153
csharp/oned/EAN13Reader.cs
Executable file
153
csharp/oned/EAN13Reader.cs
Executable file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> <p>Implements decoding of the EAN-13 format.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author> alasdair@google.com (Alasdair Mackintosh)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class EAN13Reader:UPCEANReader
|
||||
{
|
||||
override internal BarcodeFormat BarcodeFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return BarcodeFormat.EAN_13;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'FIRST_DIGIT_ENCODINGS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int[] FIRST_DIGIT_ENCODINGS = new int[]{0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A};
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'decodeMiddleCounters '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int[] decodeMiddleCounters;
|
||||
|
||||
public EAN13Reader()
|
||||
{
|
||||
decodeMiddleCounters = new int[4];
|
||||
}
|
||||
|
||||
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.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));
|
||||
for (int i = 0; i < counters.Length; i++)
|
||||
{
|
||||
rowOffset += counters[i];
|
||||
}
|
||||
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));
|
||||
for (int i = 0; i < counters.Length; i++)
|
||||
{
|
||||
rowOffset += counters[i];
|
||||
}
|
||||
}
|
||||
|
||||
return rowOffset;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException if first digit cannot be determined </throws>
|
||||
private static void determineFirstDigit(System.Text.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 ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
}
|
84
csharp/oned/EAN13Writer.cs
Executable file
84
csharp/oned/EAN13Writer.cs
Executable file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using WriterException = com.google.zxing.WriterException;
|
||||
using ByteMatrix = com.google.zxing.common.ByteMatrix;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
|
||||
/// <summary> This object renders an EAN13 code as a ByteMatrix 2D array of greyscale
|
||||
/// values.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> aripollak@gmail.com (Ari Pollak)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class EAN13Writer:UPCEANWriter
|
||||
{
|
||||
|
||||
private const int codeWidth = 3 + (7 * 6) + 5 + (7 * 6) + 3; // end guard
|
||||
|
||||
public override ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height, System.Collections.Hashtable 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 sbyte[] encode(System.String contents)
|
||||
{
|
||||
if (contents.Length != 13)
|
||||
{
|
||||
throw new System.ArgumentException("Requested contents should be 13 digits long, but got " + contents.Length);
|
||||
}
|
||||
|
||||
int firstDigit = System.Int32.Parse(contents.Substring(0, (1) - (0)));
|
||||
int parities = EAN13Reader.FIRST_DIGIT_ENCODINGS[firstDigit];
|
||||
sbyte[] result = new sbyte[codeWidth];
|
||||
int pos = 0;
|
||||
|
||||
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, 1);
|
||||
|
||||
// See {@link #EAN13Reader} for a description of how the first digit & left bars are encoded
|
||||
for (int i = 1; i <= 6; i++)
|
||||
{
|
||||
int digit = System.Int32.Parse(contents.Substring(i, (i + 1) - (i)));
|
||||
if ((parities >> (6 - i) & 1) == 1)
|
||||
{
|
||||
digit += 10;
|
||||
}
|
||||
pos += appendPattern(result, pos, UPCEANReader.L_AND_G_PATTERNS[digit], 0);
|
||||
}
|
||||
|
||||
pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, 0);
|
||||
|
||||
for (int i = 7; i <= 12; i++)
|
||||
{
|
||||
int digit = System.Int32.Parse(contents.Substring(i, (i + 1) - (i)));
|
||||
pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], 1);
|
||||
}
|
||||
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
85
csharp/oned/EAN8Reader.cs
Executable file
85
csharp/oned/EAN8Reader.cs
Executable file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> <p>Implements decoding of the EAN-8 format.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class EAN8Reader:UPCEANReader
|
||||
{
|
||||
override internal BarcodeFormat BarcodeFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return BarcodeFormat.EAN_8;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'decodeMiddleCounters '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private int[] decodeMiddleCounters;
|
||||
|
||||
public EAN8Reader()
|
||||
{
|
||||
decodeMiddleCounters = new int[4];
|
||||
}
|
||||
|
||||
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.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));
|
||||
for (int i = 0; i < counters.Length; i++)
|
||||
{
|
||||
rowOffset += counters[i];
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
for (int i = 0; i < counters.Length; i++)
|
||||
{
|
||||
rowOffset += counters[i];
|
||||
}
|
||||
}
|
||||
|
||||
return rowOffset;
|
||||
}
|
||||
}
|
||||
}
|
78
csharp/oned/EAN8Writer.cs
Executable file
78
csharp/oned/EAN8Writer.cs
Executable file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using WriterException = com.google.zxing.WriterException;
|
||||
using ByteMatrix = com.google.zxing.common.ByteMatrix;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> This object renders an EAN8 code as a ByteMatrix 2D array of greyscale
|
||||
/// values.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> aripollak@gmail.com (Ari Pollak)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class EAN8Writer:UPCEANWriter
|
||||
{
|
||||
|
||||
private const int codeWidth = 3 + (7 * 4) + 5 + (7 * 4) + 3; // end guard
|
||||
|
||||
public override ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height, System.Collections.Hashtable 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 (0 = white, 1 = black)
|
||||
/// </returns>
|
||||
public override sbyte[] encode(System.String contents)
|
||||
{
|
||||
if (contents.Length != 8)
|
||||
{
|
||||
throw new System.ArgumentException("Requested contents should be 8 digits long, but got " + contents.Length);
|
||||
}
|
||||
|
||||
sbyte[] result = new sbyte[codeWidth];
|
||||
int pos = 0;
|
||||
|
||||
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, 1);
|
||||
|
||||
for (int i = 0; i <= 3; i++)
|
||||
{
|
||||
int digit = System.Int32.Parse(contents.Substring(i, (i + 1) - (i)));
|
||||
pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], 0);
|
||||
}
|
||||
|
||||
pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, 0);
|
||||
|
||||
for (int i = 4; i <= 7; i++)
|
||||
{
|
||||
int digit = System.Int32.Parse(contents.Substring(i, (i + 1) - (i)));
|
||||
pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], 1);
|
||||
}
|
||||
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
382
csharp/oned/ITFReader.cs
Executable file
382
csharp/oned/ITFReader.cs
Executable file
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using DecodeHintType = com.google.zxing.DecodeHintType;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
using ResultPoint = com.google.zxing.ResultPoint;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> <p>Implements decoding of the ITF format.</p>
|
||||
///
|
||||
/// <p>"ITF" stands for Interleaved Two of Five. This Reader will scan ITF barcode with 6, 10 or 14
|
||||
/// digits. 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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> kevin.osullivan@sita.aero, SITA Lab.
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class ITFReader:OneDReader
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'MAX_AVG_VARIANCE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
private static readonly int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'MAX_INDIVIDUAL_VARIANCE '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
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
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'DEFAULT_ALLOWED_LENGTHS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int[] DEFAULT_ALLOWED_LENGTHS = new int[]{6, 10, 14, 44};
|
||||
|
||||
// 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>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'START_PATTERN '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int[] START_PATTERN = new int[]{N, N, N, N};
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'END_PATTERN_REVERSED '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int[] END_PATTERN_REVERSED = new int[]{N, N, W};
|
||||
|
||||
/// <summary> Patterns of Wide / Narrow lines to indicate each digit</summary>
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'PATTERNS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private static readonly int[][] PATTERNS = new int[][]{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}};
|
||||
|
||||
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
|
||||
{
|
||||
|
||||
// Find out where the Middle section (payload) starts & ends
|
||||
int[] startRange = decodeStart(row);
|
||||
int[] endRange = decodeEnd(row);
|
||||
|
||||
System.Text.StringBuilder result = new System.Text.StringBuilder(20);
|
||||
decodeMiddle(row, startRange[1], endRange[0], result);
|
||||
System.String resultString = result.ToString();
|
||||
|
||||
int[] allowedLengths = null;
|
||||
if (hints != null)
|
||||
{
|
||||
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;
|
||||
for (int i = 0; i < allowedLengths.Length; i++)
|
||||
{
|
||||
if (length == allowedLengths[i])
|
||||
{
|
||||
lengthOK = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!lengthOK)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
|
||||
return new Result(resultString, null, new ResultPoint[]{new ResultPoint(startRange[1], (float) rowNumber), new ResultPoint(endRange[0], (float) rowNumber)}, BarcodeFormat.ITF);
|
||||
}
|
||||
|
||||
/// <param name="row"> row of black/white values to search
|
||||
/// </param>
|
||||
/// <param name="payloadStart">offset of start pattern
|
||||
/// </param>
|
||||
/// <param name="resultString">{@link StringBuffer} to append decoded chars to
|
||||
/// </param>
|
||||
/// <throws> ReaderException if decoding could not complete successfully </throws>
|
||||
private static void decodeMiddle(BitArray row, int payloadStart, int payloadEnd, System.Text.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));
|
||||
|
||||
for (int i = 0; i < counterDigitPair.Length; i++)
|
||||
{
|
||||
payloadStart += counterDigitPair[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException </throws>
|
||||
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>
|
||||
/// <throws> ReaderException if the quiet zone cannot be found, a ReaderException is thrown. </throws>
|
||||
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_Renamed(i))
|
||||
{
|
||||
break;
|
||||
}
|
||||
quietCount--;
|
||||
}
|
||||
if (quietCount != 0)
|
||||
{
|
||||
// Unable to find the necessary number of quiet zone pixels.
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException Throws exception if no black lines are found in the row </throws>
|
||||
private static int skipWhiteSpace(BitArray row)
|
||||
{
|
||||
int width = row.Size;
|
||||
int endStart = 0;
|
||||
while (endStart < width)
|
||||
{
|
||||
if (row.get_Renamed(endStart))
|
||||
{
|
||||
break;
|
||||
}
|
||||
endStart++;
|
||||
}
|
||||
if (endStart == width)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
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>
|
||||
/// <throws> ReaderException </throws>
|
||||
|
||||
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>
|
||||
/// <throws> ReaderException if pattern is not found </throws>
|
||||
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++)
|
||||
{
|
||||
bool pixel = row.get_Renamed(x);
|
||||
if (pixel ^ 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];
|
||||
for (int y = 2; y < patternLength; y++)
|
||||
{
|
||||
counters[y - 2] = counters[y];
|
||||
}
|
||||
counters[patternLength - 2] = 0;
|
||||
counters[patternLength - 1] = 0;
|
||||
counterPosition--;
|
||||
}
|
||||
else
|
||||
{
|
||||
counterPosition++;
|
||||
}
|
||||
counters[counterPosition] = 1;
|
||||
isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException if digit cannot be decoded </throws>
|
||||
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 ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
89
csharp/oned/MultiFormatOneDReader.cs
Executable file
89
csharp/oned/MultiFormatOneDReader.cs
Executable file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using DecodeHintType = com.google.zxing.DecodeHintType;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class MultiFormatOneDReader:OneDReader
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'readers '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.Collections.ArrayList readers;
|
||||
|
||||
public MultiFormatOneDReader(System.Collections.Hashtable hints)
|
||||
{
|
||||
System.Collections.ArrayList possibleFormats = hints == null?null:(System.Collections.ArrayList) hints[DecodeHintType.POSSIBLE_FORMATS];
|
||||
bool useCode39CheckDigit = hints != null && hints[DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT] != null;
|
||||
readers = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
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_128))
|
||||
{
|
||||
readers.Add(new Code128Reader());
|
||||
}
|
||||
if (possibleFormats.Contains(BarcodeFormat.ITF))
|
||||
{
|
||||
readers.Add(new ITFReader());
|
||||
}
|
||||
}
|
||||
if ((readers.Count == 0))
|
||||
{
|
||||
readers.Add(new MultiFormatUPCEANReader(hints));
|
||||
readers.Add(new Code39Reader());
|
||||
readers.Add(new Code128Reader());
|
||||
readers.Add(new ITFReader());
|
||||
}
|
||||
}
|
||||
|
||||
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
|
||||
{
|
||||
int size = readers.Count;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
OneDReader reader = (OneDReader) readers[i];
|
||||
try
|
||||
{
|
||||
return reader.decodeRow(rowNumber, row, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
}
|
109
csharp/oned/MultiFormatUPCEANReader.cs
Executable file
109
csharp/oned/MultiFormatUPCEANReader.cs
Executable file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using DecodeHintType = com.google.zxing.DecodeHintType;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <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>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class MultiFormatUPCEANReader:OneDReader
|
||||
{
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'readers '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private System.Collections.ArrayList readers;
|
||||
|
||||
public MultiFormatUPCEANReader(System.Collections.Hashtable hints)
|
||||
{
|
||||
System.Collections.ArrayList possibleFormats = hints == null?null:(System.Collections.ArrayList) hints[DecodeHintType.POSSIBLE_FORMATS];
|
||||
readers = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
|
||||
{
|
||||
// Compute this location once and reuse it on multiple implementations
|
||||
int[] startGuardPattern = UPCEANReader.findStartGuardPattern(row);
|
||||
int size = readers.Count;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
UPCEANReader reader = (UPCEANReader) readers[i];
|
||||
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.
|
||||
if (result.BarcodeFormat.Equals(BarcodeFormat.EAN_13) && result.Text[0] == '0')
|
||||
{
|
||||
return new Result(result.Text.Substring(1), null, result.ResultPoints, BarcodeFormat.UPC_A);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
}
|
332
csharp/oned/OneDReader.cs
Executable file
332
csharp/oned/OneDReader.cs
Executable file
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* 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 BinaryBitmap = com.google.zxing.BinaryBitmap;
|
||||
using DecodeHintType = com.google.zxing.DecodeHintType;
|
||||
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;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> Encapsulates functionality and implementation that is common to all families
|
||||
/// of one-dimensional barcodes.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public abstract class OneDReader : Reader
|
||||
{
|
||||
|
||||
private const int INTEGER_MATH_SHIFT = 8;
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'PATTERN_MATCH_RESULT_SCALE_FACTOR '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
internal static readonly int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT;
|
||||
|
||||
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.
|
||||
public virtual Result decode(BinaryBitmap image, System.Collections.Hashtable hints)
|
||||
{
|
||||
try
|
||||
{
|
||||
return doDecode(image, hints);
|
||||
}
|
||||
catch (ReaderException re)
|
||||
{
|
||||
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
|
||||
System.Collections.Hashtable 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 + ((System.Int32) metadata[ResultMetadataType.ORIENTATION])) % 360;
|
||||
}
|
||||
result.putMetadata(ResultMetadataType.ORIENTATION, (System.Object) orientation);
|
||||
// Update result points
|
||||
ResultPoint[] points = result.ResultPoints;
|
||||
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 re;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException Any spontaneous errors which occur </throws>
|
||||
private Result doDecode(BinaryBitmap image, System.Collections.Hashtable 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 = System.Math.Max(1, height >> (tryHarder?7:4));
|
||||
int maxLines;
|
||||
if (tryHarder)
|
||||
{
|
||||
maxLines = height; // Look at the whole image, not just the center
|
||||
}
|
||||
else
|
||||
{
|
||||
maxLines = 9; // Nine rows spaced 1/16 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 (ReaderException re)
|
||||
{
|
||||
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))
|
||||
{
|
||||
System.Collections.Hashtable newHints = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable()); // Can't use clone() in J2ME
|
||||
System.Collections.IEnumerator hintEnum = hints.Keys.GetEnumerator();
|
||||
//UPGRADE_TODO: Method 'java.util.Enumeration.hasMoreElements' was converted to 'System.Collections.IEnumerator.MoveNext' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationhasMoreElements'"
|
||||
while (hintEnum.MoveNext())
|
||||
{
|
||||
//UPGRADE_TODO: Method 'java.util.Enumeration.nextElement' was converted to 'System.Collections.IEnumerator.Current' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javautilEnumerationnextElement'"
|
||||
System.Object key = hintEnum.Current;
|
||||
if (!key.Equals(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
|
||||
{
|
||||
newHints[key] = hints[key];
|
||||
}
|
||||
}
|
||||
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, (System.Object) 180);
|
||||
// And remember to flip the result points horizontally.
|
||||
ResultPoint[] points = result.ResultPoints;
|
||||
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 ReaderException.Instance;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <throws> ReaderException if counters cannot be filled entirely from row before running out </throws>
|
||||
/// <summary> of pixels
|
||||
/// </summary>
|
||||
internal static void recordPattern(BitArray row, int start, int[] counters)
|
||||
{
|
||||
int numCounters = counters.Length;
|
||||
for (int i = 0; i < numCounters; i++)
|
||||
{
|
||||
counters[i] = 0;
|
||||
}
|
||||
int end = row.Size;
|
||||
if (start >= end)
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
bool isWhite = !row.get_Renamed(start);
|
||||
int counterPosition = 0;
|
||||
int i2 = start;
|
||||
while (i2 < end)
|
||||
{
|
||||
bool pixel = row.get_Renamed(i2);
|
||||
if (pixel ^ isWhite)
|
||||
{
|
||||
// that is, exactly one is true
|
||||
counters[counterPosition]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
counterPosition++;
|
||||
if (counterPosition == numCounters)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
counters[counterPosition] = 1;
|
||||
isWhite ^= true; // isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
i2++;
|
||||
}
|
||||
// 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 && i2 == end)))
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
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 System.Int32.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 System.Int32.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> {@link Result} containing encoded string and start/end of barcode
|
||||
/// </returns>
|
||||
/// <throws> ReaderException if an error occurs or barcode cannot be found </throws>
|
||||
public abstract Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints);
|
||||
}
|
||||
}
|
86
csharp/oned/UPCAReader.cs
Executable file
86
csharp/oned/UPCAReader.cs
Executable file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 BarcodeFormat = com.google.zxing.BarcodeFormat;
|
||||
using ReaderException = com.google.zxing.ReaderException;
|
||||
using Result = com.google.zxing.Result;
|
||||
using BinaryBitmap = com.google.zxing.BinaryBitmap;
|
||||
using BitArray = com.google.zxing.common.BitArray;
|
||||
namespace com.google.zxing.oned
|
||||
{
|
||||
|
||||
/// <summary> <p>Implements decoding of the UPC-A format.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class UPCAReader:UPCEANReader
|
||||
{
|
||||
override internal BarcodeFormat BarcodeFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return BarcodeFormat.UPC_A;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//UPGRADE_NOTE: Final was removed from the declaration of 'ean13Reader '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
|
||||
private UPCEANReader ean13Reader = new EAN13Reader();
|
||||
|
||||
public override Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, System.Collections.Hashtable hints)
|
||||
{
|
||||
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange, hints));
|
||||
}
|
||||
|
||||
public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
|
||||
{
|
||||
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints));
|
||||
}
|
||||
|
||||
public override Result decode(BinaryBitmap image)
|
||||
{
|
||||
return maybeReturnResult(ean13Reader.decode(image));
|
||||
}
|
||||
|
||||
public override Result decode(BinaryBitmap image, System.Collections.Hashtable hints)
|
||||
{
|
||||
return maybeReturnResult(ean13Reader.decode(image, hints));
|
||||
}
|
||||
|
||||
protected internal override int decodeMiddle(BitArray row, int[] startRange, System.Text.StringBuilder resultString)
|
||||
{
|
||||
return ean13Reader.decodeMiddle(row, startRange, resultString);
|
||||
}
|
||||
|
||||
private static Result maybeReturnResult(Result result)
|
||||
{
|
||||
System.String text = result.Text;
|
||||
if (text[0] == '0')
|
||||
{
|
||||
return new Result(text.Substring(1), null, result.ResultPoints, BarcodeFormat.UPC_A);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ReaderException.Instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue