@@ -0,0 +1,152 @@ | |||
/* | |||
* Copyright 2012 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
#if !PORTABLE | |||
#if !(SILVERLIGHT || NETFX_CORE) | |||
#if !UNITY | |||
using System.Drawing; | |||
using ZXing.QrCode; | |||
#else | |||
using UnityEngine; | |||
#endif | |||
#elif NETFX_CORE | |||
using Windows.UI.Xaml.Media.Imaging; | |||
#else | |||
using System.Windows.Media.Imaging; | |||
#endif | |||
#endif | |||
#if MONOANDROID | |||
using Android.Graphics; | |||
#endif | |||
namespace ZXing | |||
{ | |||
/// <summary> | |||
/// A smart class to decode the barcode inside a bitmap object | |||
/// </summary> | |||
#if MONOTOUCH | |||
public class BarcodeReader : BarcodeReaderGeneric<MonoTouch.UIKit.UIImage>, IBarcodeReader, IMultipleBarcodeReader | |||
{ | |||
private static readonly Func<MonoTouch.UIKit.UIImage, LuminanceSource> defaultCreateLuminanceSource = | |||
(img) => new RGBLuminanceSource(img); | |||
#else | |||
#if !PORTABLE | |||
#if !(SILVERLIGHT || NETFX_CORE) | |||
#if !UNITY | |||
public class BarcodeReader : BarcodeReaderGeneric<Bitmap>, IBarcodeReader | |||
{ | |||
private static readonly Func<Bitmap, LuminanceSource> defaultCreateLuminanceSource = | |||
(bitmap) => new BitmapLuminanceSource(bitmap); | |||
#else | |||
public class BarcodeReader : BarcodeReaderGeneric<Color32[]>, IBarcodeReader, IMultipleBarcodeReader | |||
{ | |||
private static readonly Func<Color32[], int, int, LuminanceSource> defaultCreateLuminanceSource = | |||
(rawColor32, width, height) => new Color32LuminanceSource(rawColor32, width, height); | |||
#endif | |||
#else | |||
public class BarcodeReader : BarcodeReaderGeneric<WriteableBitmap>, IBarcodeReader, IMultipleBarcodeReader | |||
{ | |||
private static readonly Func<WriteableBitmap, LuminanceSource> defaultCreateLuminanceSource = | |||
(bitmap) => new BitmapLuminanceSource(bitmap); | |||
#endif | |||
#else | |||
public class BarcodeReader : BarcodeReaderGeneric<byte[]>, IBarcodeReader, IMultipleBarcodeReader | |||
{ | |||
private static readonly Func<byte[], LuminanceSource> defaultCreateLuminanceSource = | |||
(data) => null; | |||
#endif | |||
#endif | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class. | |||
/// </summary> | |||
public BarcodeReader() | |||
: this(new QRCodeReader(), defaultCreateLuminanceSource, null) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class. | |||
/// </summary> | |||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode. | |||
/// If null then MultiFormatReader is used</param> | |||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap. | |||
/// If null, an exception is thrown when Decode is called</param> | |||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source. | |||
/// If null then HybridBinarizer is used</param> | |||
public BarcodeReader(Reader reader, | |||
#if MONOTOUCH | |||
Func<MonoTouch.UIKit.UIImage, LuminanceSource> createLuminanceSource, | |||
#elif MONOANDROID | |||
Func<Android.Graphics.Bitmap, LuminanceSource> createLuminanceSource, | |||
#else | |||
#if !(SILVERLIGHT || NETFX_CORE) | |||
#if !UNITY | |||
#if !PORTABLE | |||
Func<Bitmap, LuminanceSource> createLuminanceSource, | |||
#else | |||
Func<byte[], LuminanceSource> createLuminanceSource, | |||
#endif | |||
#else | |||
Func<Color32[], int, int, LuminanceSource> createLuminanceSource, | |||
#endif | |||
#else | |||
Func<WriteableBitmap, LuminanceSource> createLuminanceSource, | |||
#endif | |||
#endif | |||
Func<LuminanceSource, Binarizer> createBinarizer | |||
) | |||
: base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class. | |||
/// </summary> | |||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode. | |||
/// If null then MultiFormatReader is used</param> | |||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap. | |||
/// If null, an exception is thrown when Decode is called</param> | |||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source. | |||
/// If null then HybridBinarizer is used</param> | |||
public BarcodeReader(Reader reader, | |||
#if MONOTOUCH | |||
Func<MonoTouch.UIKit.UIImage, LuminanceSource> createLuminanceSource, | |||
#elif MONOANDROID | |||
Func<Android.Graphics.Bitmap, LuminanceSource> createLuminanceSource, | |||
#else | |||
#if !(SILVERLIGHT || NETFX_CORE) | |||
#if !UNITY | |||
#if !PORTABLE | |||
Func<Bitmap, LuminanceSource> createLuminanceSource, | |||
#else | |||
Func<byte[], LuminanceSource> createLuminanceSource, | |||
#endif | |||
#else | |||
Func<Color32[], int, int, LuminanceSource> createLuminanceSource, | |||
#endif | |||
#else | |||
Func<WriteableBitmap, LuminanceSource> createLuminanceSource, | |||
#endif | |||
#endif | |||
Func<LuminanceSource, Binarizer> createBinarizer, | |||
Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource | |||
) | |||
: base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer, createRGBLuminanceSource) | |||
{ | |||
} | |||
} | |||
} |
@@ -0,0 +1,436 @@ | |||
/* | |||
* Copyright 2012 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
using ZXing.Common; | |||
using ZXing.QrCode; | |||
namespace ZXing | |||
{ | |||
/// <summary> | |||
/// A smart class to decode the barcode inside a bitmap object | |||
/// </summary> | |||
public class BarcodeReaderGeneric<T> : IBarcodeReaderGeneric<T> | |||
{ | |||
private static readonly Func<LuminanceSource, Binarizer> defaultCreateBinarizer = | |||
(luminanceSource) => new HybridBinarizer(luminanceSource); | |||
protected static readonly Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> defaultCreateRGBLuminanceSource = | |||
(rawBytes, width, height, format) => new RGBLuminanceSource(rawBytes, width, height, format); | |||
private Reader reader; | |||
private readonly Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource; | |||
#if !UNITY | |||
private readonly Func<T, LuminanceSource> createLuminanceSource; | |||
#else | |||
private readonly Func<T, int, int, LuminanceSource> createLuminanceSource; | |||
#endif | |||
private readonly Func<LuminanceSource, Binarizer> createBinarizer; | |||
private bool usePreviousState; | |||
private DecodingOptions options; | |||
/// <summary> | |||
/// Gets or sets the options. | |||
/// </summary> | |||
/// <value> | |||
/// The options. | |||
/// </value> | |||
public DecodingOptions Options | |||
{ | |||
get { return options ?? (options = new DecodingOptions()); } | |||
set { options = value; } | |||
} | |||
/// <summary> | |||
/// Gets the reader which should be used to find and decode the barcode. | |||
/// </summary> | |||
/// <value> | |||
/// The reader. | |||
/// </value> | |||
protected Reader Reader | |||
{ | |||
get | |||
{ | |||
return reader ?? (reader = new QRCodeReader()); | |||
} | |||
} | |||
/// <summary> | |||
/// Gets or sets a method which is called if an important point is found | |||
/// </summary> | |||
/// <value> | |||
/// The result point callback. | |||
/// </value> | |||
public event Action<ResultPoint> ResultPointFound | |||
{ | |||
add | |||
{ | |||
if (!Options.Hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) | |||
{ | |||
var callback = new ResultPointCallback(OnResultPointFound); | |||
Options.Hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK] = callback; | |||
} | |||
explicitResultPointFound += value; | |||
usePreviousState = false; | |||
} | |||
remove | |||
{ | |||
explicitResultPointFound -= value; | |||
if (explicitResultPointFound == null) | |||
Options.Hints.Remove(DecodeHintType.NEED_RESULT_POINT_CALLBACK); | |||
usePreviousState = false; | |||
} | |||
} | |||
private event Action<ResultPoint> explicitResultPointFound; | |||
/// <summary> | |||
/// event is executed if a result was found via decode | |||
/// </summary> | |||
public event Action<Result> ResultFound; | |||
/// <summary> | |||
/// Gets or sets a flag which cause a deeper look into the bitmap | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if [try harder]; otherwise, <c>false</c>. | |||
/// </value> | |||
[Obsolete("Please use the Options.TryHarder property instead.")] | |||
public bool TryHarder | |||
{ | |||
get { return Options.TryHarder; } | |||
set { Options.TryHarder = value; } | |||
} | |||
/// <summary> | |||
/// Image is a pure monochrome image of a barcode. | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if monochrome image of a barcode; otherwise, <c>false</c>. | |||
/// </value> | |||
[Obsolete("Please use the Options.PureBarcode property instead.")] | |||
public bool PureBarcode | |||
{ | |||
get { return Options.PureBarcode; } | |||
set { Options.PureBarcode = value; } | |||
} | |||
/// <summary> | |||
/// Specifies what character encoding to use when decoding, where applicable (type String) | |||
/// </summary> | |||
/// <value> | |||
/// The character set. | |||
/// </value> | |||
[Obsolete("Please use the Options.CharacterSet property instead.")] | |||
public string CharacterSet | |||
{ | |||
get { return Options.CharacterSet; } | |||
set { Options.CharacterSet = value; } | |||
} | |||
/// <summary> | |||
/// Image is known to be of one of a few possible formats. | |||
/// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. | |||
/// </summary> | |||
/// <value> | |||
/// The possible formats. | |||
/// </value> | |||
[Obsolete("Please use the Options.PossibleFormats property instead.")] | |||
public IList<BarcodeFormat> PossibleFormats | |||
{ | |||
get { return Options.PossibleFormats; } | |||
set { Options.PossibleFormats = value; } | |||
} | |||
/// <summary> | |||
/// Gets or sets a value indicating whether the image should be automatically rotated. | |||
/// Rotation is supported for 90, 180 and 270 degrees | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if image should be rotated; otherwise, <c>false</c>. | |||
/// </value> | |||
public bool AutoRotate { get; set; } | |||
/// <summary> | |||
/// Gets or sets a value indicating whether the image should be automatically inverted | |||
/// if no result is found in the original image. | |||
/// ATTENTION: Please be carefully because it slows down the decoding process if it is used | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if image should be inverted; otherwise, <c>false</c>. | |||
/// </value> | |||
public bool TryInverted { get; set; } | |||
#if !UNITY | |||
/// <summary> | |||
/// Optional: Gets or sets the function to create a luminance source object for a bitmap. | |||
/// If null a platform specific default LuminanceSource is used | |||
/// </summary> | |||
/// <value> | |||
/// The function to create a luminance source object. | |||
/// </value> | |||
protected Func<T, LuminanceSource> CreateLuminanceSource | |||
#else | |||
/// <summary> | |||
/// Optional: Gets or sets the function to create a luminance source object for a bitmap. | |||
/// If null a platform specific default LuminanceSource is used | |||
/// </summary> | |||
/// <value> | |||
/// The function to create a luminance source object. | |||
/// </value> | |||
protected Func<T, int, int, LuminanceSource> CreateLuminanceSource | |||
#endif | |||
{ | |||
get | |||
{ | |||
return createLuminanceSource; | |||
} | |||
} | |||
/// <summary> | |||
/// Optional: Gets or sets the function to create a binarizer object for a luminance source. | |||
/// If null then HybridBinarizer is used | |||
/// </summary> | |||
/// <value> | |||
/// The function to create a binarizer object. | |||
/// </value> | |||
protected Func<LuminanceSource, Binarizer> CreateBinarizer | |||
{ | |||
get | |||
{ | |||
return createBinarizer ?? defaultCreateBinarizer; | |||
} | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="BarcodeReaderGeneric{T}"/> class. | |||
/// </summary> | |||
public BarcodeReaderGeneric() | |||
: this(new QRCodeReader(), null, defaultCreateBinarizer) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="BarcodeReaderGeneric{T}"/> class. | |||
/// </summary> | |||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode. | |||
/// If null then MultiFormatReader is used</param> | |||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap. | |||
/// If null, an exception is thrown when Decode is called</param> | |||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source. | |||
/// If null then HybridBinarizer is used</param> | |||
public BarcodeReaderGeneric(Reader reader, | |||
#if !UNITY | |||
Func<T, LuminanceSource> createLuminanceSource, | |||
#else | |||
Func<T, int, int, LuminanceSource> createLuminanceSource, | |||
#endif | |||
Func<LuminanceSource, Binarizer> createBinarizer | |||
) | |||
: this(reader, createLuminanceSource, createBinarizer, null) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="BarcodeReaderGeneric{T}"/> class. | |||
/// </summary> | |||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode. | |||
/// If null then MultiFormatReader is used</param> | |||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap. | |||
/// If null, an exception is thrown when Decode is called</param> | |||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source. | |||
/// If null then HybridBinarizer is used</param> | |||
/// <param name="createRGBLuminanceSource">Sets the function to create a luminance source object for a rgb array. | |||
/// If null the RGBLuminanceSource is used. The handler is only called when Decode with a byte[] array is called.</param> | |||
public BarcodeReaderGeneric(Reader reader, | |||
#if !UNITY | |||
Func<T, LuminanceSource> createLuminanceSource, | |||
#else | |||
Func<T, int, int, LuminanceSource> createLuminanceSource, | |||
#endif | |||
Func<LuminanceSource, Binarizer> createBinarizer, | |||
Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource | |||
) | |||
{ | |||
this.reader = reader ?? new QRCodeReader(); | |||
this.createLuminanceSource = createLuminanceSource; | |||
this.createBinarizer = createBinarizer ?? defaultCreateBinarizer; | |||
this.createRGBLuminanceSource = createRGBLuminanceSource ?? defaultCreateRGBLuminanceSource; | |||
Options.ValueChanged += (o, args) => usePreviousState = false; | |||
usePreviousState = false; | |||
} | |||
#if !PORTABLE | |||
#if !UNITY | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="barcodeBitmap">The barcode bitmap.</param> | |||
/// <returns>the result data or null</returns> | |||
public Result Decode(T barcodeBitmap) | |||
#else | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="rawRGB">raw bytes of the image in RGB order</param> | |||
/// <param name="width"></param> | |||
/// <param name="height"></param> | |||
/// <returns> | |||
/// the result data or null | |||
/// </returns> | |||
public Result Decode(T rawRGB, int width, int height) | |||
#endif | |||
{ | |||
if (CreateLuminanceSource == null) | |||
{ | |||
throw new InvalidOperationException("You have to declare a luminance source delegate."); | |||
} | |||
#if !UNITY | |||
if (barcodeBitmap == null) | |||
throw new ArgumentNullException("barcodeBitmap"); | |||
#else | |||
if (rawRGB == null) | |||
throw new ArgumentNullException("rawRGB"); | |||
#endif | |||
#if !UNITY | |||
var luminanceSource = CreateLuminanceSource(barcodeBitmap); | |||
#else | |||
var luminanceSource = CreateLuminanceSource(rawRGB, width, height); | |||
#endif | |||
return Decode(luminanceSource); | |||
} | |||
#endif | |||
/// <summary> | |||
/// Tries to decode a barcode within an image which is given by a luminance source. | |||
/// That method gives a chance to prepare a luminance source completely before calling | |||
/// the time consuming decoding method. On the other hand there is a chance to create | |||
/// a luminance source which is independent from external resources (like Bitmap objects) | |||
/// and the decoding call can be made in a background thread. | |||
/// </summary> | |||
/// <param name="luminanceSource">The luminance source.</param> | |||
/// <returns></returns> | |||
virtual public Result Decode(LuminanceSource luminanceSource) | |||
{ | |||
var result = default(Result); | |||
var binarizer = CreateBinarizer(luminanceSource); | |||
var binaryBitmap = new BinaryBitmap(binarizer); | |||
var multiformatReader = Reader as QRCodeReader; | |||
var rotationCount = 0; | |||
var rotationMaxCount = 1; | |||
if (AutoRotate) | |||
{ | |||
Options.Hints[DecodeHintType.TRY_HARDER_WITHOUT_ROTATION] = true; | |||
rotationMaxCount = 4; | |||
} | |||
else | |||
{ | |||
if (Options.Hints.ContainsKey(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION)) | |||
Options.Hints.Remove(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION); | |||
} | |||
for (; rotationCount < rotationMaxCount; rotationCount++) | |||
{ | |||
result = Reader.decode(binaryBitmap, Options.Hints); | |||
usePreviousState = true; | |||
if (result != null || | |||
!luminanceSource.RotateSupported || | |||
!AutoRotate) | |||
break; | |||
binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.rotateCounterClockwise())); | |||
} | |||
if (result != null) | |||
{ | |||
if (result.ResultMetadata == null) | |||
{ | |||
result.putMetadata(ResultMetadataType.ORIENTATION, rotationCount * 90); | |||
} | |||
else if (!result.ResultMetadata.ContainsKey(ResultMetadataType.ORIENTATION)) | |||
{ | |||
result.ResultMetadata[ResultMetadataType.ORIENTATION] = rotationCount * 90; | |||
} | |||
else | |||
{ | |||
// perhaps the core decoder rotates the image already (can happen if TryHarder is specified) | |||
result.ResultMetadata[ResultMetadataType.ORIENTATION] = ((int)(result.ResultMetadata[ResultMetadataType.ORIENTATION]) + rotationCount * 90) % 360; | |||
} | |||
OnResultFound(result); | |||
} | |||
return result; | |||
} | |||
protected void OnResultsFound(IEnumerable<Result> results) | |||
{ | |||
if (ResultFound != null) | |||
{ | |||
foreach (var result in results) | |||
{ | |||
ResultFound(result); | |||
} | |||
} | |||
} | |||
protected void OnResultFound(Result result) | |||
{ | |||
if (ResultFound != null) | |||
{ | |||
ResultFound(result); | |||
} | |||
} | |||
protected void OnResultPointFound(ResultPoint resultPoint) | |||
{ | |||
if (explicitResultPointFound != null) | |||
{ | |||
explicitResultPointFound(resultPoint); | |||
} | |||
} | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="rawRGB">The image as byte[] array.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <param name="format">The format.</param> | |||
/// <returns> | |||
/// the result data or null | |||
/// </returns> | |||
public Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format) | |||
{ | |||
if (rawRGB == null) | |||
throw new ArgumentNullException("rawRGB"); | |||
var luminanceSource = createRGBLuminanceSource(rawRGB, width, height, format); | |||
return Decode(luminanceSource); | |||
} | |||
} | |||
} |
@@ -0,0 +1,161 @@ | |||
/* | |||
* Copyright 2012 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
#if !(SILVERLIGHT || NETFX_CORE) | |||
#if !UNITY | |||
#if !PORTABLE | |||
using System.Drawing; | |||
#endif | |||
#else | |||
using UnityEngine; | |||
#endif | |||
#elif NETFX_CORE | |||
using Windows.UI.Xaml.Media.Imaging; | |||
#else | |||
using System.Windows.Media.Imaging; | |||
#endif | |||
using ZXing.Common; | |||
namespace ZXing | |||
{ | |||
/// <summary> | |||
/// Interface for a smart class to decode the barcode inside a bitmap object | |||
/// </summary> | |||
public interface IBarcodeReader | |||
{ | |||
/// <summary> | |||
/// event is executed when a result point was found | |||
/// </summary> | |||
event Action<ResultPoint> ResultPointFound; | |||
/// <summary> | |||
/// event is executed when a result was found via decode | |||
/// </summary> | |||
event Action<Result> ResultFound; | |||
/// <summary> | |||
/// Gets or sets a flag which cause a deeper look into the bitmap | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if [try harder]; otherwise, <c>false</c>. | |||
/// </value> | |||
[Obsolete("Please use the Options.TryHarder property instead.")] | |||
bool TryHarder { get; set; } | |||
/// <summary> | |||
/// Image is a pure monochrome image of a barcode. | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if monochrome image of a barcode; otherwise, <c>false</c>. | |||
/// </value> | |||
[Obsolete("Please use the Options.PureBarcode property instead.")] | |||
bool PureBarcode { get; set; } | |||
/// <summary> | |||
/// Specifies what character encoding to use when decoding, where applicable (type String) | |||
/// </summary> | |||
/// <value> | |||
/// The character set. | |||
/// </value> | |||
[Obsolete("Please use the Options.CharacterSet property instead.")] | |||
string CharacterSet { get; set; } | |||
/// <summary> | |||
/// Image is known to be of one of a few possible formats. | |||
/// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. | |||
/// </summary> | |||
/// <value> | |||
/// The possible formats. | |||
/// </value> | |||
[Obsolete("Please use the Options.PossibleFormats property instead.")] | |||
IList<BarcodeFormat> PossibleFormats { get; set; } | |||
/// <summary> | |||
/// Specifies some options which influence the decoding process | |||
/// </summary> | |||
DecodingOptions Options { get; set; } | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap which is given by a generic byte array with the order RGB24. | |||
/// </summary> | |||
/// <param name="rawRGB">The image as RGB24 array.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <param name="format">The format.</param> | |||
/// <returns> | |||
/// the result data or null | |||
/// </returns> | |||
Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format); | |||
/// <summary> | |||
/// Tries to decode a barcode within an image which is given by a luminance source. | |||
/// That method gives a chance to prepare a luminance source completely before calling | |||
/// the time consuming decoding method. On the other hand there is a chance to create | |||
/// a luminance source which is independent from external resources (like Bitmap objects) | |||
/// and the decoding call can be made in a background thread. | |||
/// </summary> | |||
/// <param name="luminanceSource">The luminance source.</param> | |||
/// <returns></returns> | |||
Result Decode(LuminanceSource luminanceSource); | |||
#if MONOTOUCH | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="barcodeBitmap">The barcode bitmap.</param> | |||
/// <returns>the result data or null</returns> | |||
Result Decode(MonoTouch.UIKit.UIImage barcodeImage); | |||
#elif MONOANDROID | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="barcodeBitmap">The barcode bitmap.</param> | |||
/// <returns>the result data or null</returns> | |||
Result Decode(Android.Graphics.Bitmap barcodeImage); | |||
#else | |||
#if !PORTABLE | |||
#if !(SILVERLIGHT || NETFX_CORE) | |||
#if !UNITY | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="barcodeBitmap">The barcode bitmap.</param> | |||
/// <returns>the result data or null</returns> | |||
Result Decode(Bitmap barcodeBitmap); | |||
#else | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="rawColor32">The image as Color32 array.</param> | |||
/// <returns>the result data or null</returns> | |||
Result Decode(Color32[] rawColor32, int width, int height); | |||
#endif | |||
#else | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="barcodeBitmap">The barcode bitmap.</param> | |||
/// <returns>the result data or null</returns> | |||
Result Decode(WriteableBitmap barcodeBitmap); | |||
#endif | |||
#endif | |||
#endif | |||
} | |||
} |
@@ -0,0 +1,123 @@ | |||
/* | |||
* Copyright 2012 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
using ZXing.Common; | |||
namespace ZXing | |||
{ | |||
/// <summary> | |||
/// Interface for a smart class to decode the barcode inside a bitmap object | |||
/// </summary> | |||
/// <typeparam name="T">gives the type of the input data</typeparam> | |||
public interface IBarcodeReaderGeneric<T> | |||
{ | |||
/// <summary> | |||
/// event is executed when a result point was found | |||
/// </summary> | |||
event Action<ResultPoint> ResultPointFound; | |||
/// <summary> | |||
/// event is executed when a result was found via decode | |||
/// </summary> | |||
event Action<Result> ResultFound; | |||
/// <summary> | |||
/// Gets or sets a flag which cause a deeper look into the bitmap | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if [try harder]; otherwise, <c>false</c>. | |||
/// </value> | |||
[Obsolete("Please use the Options.TryHarder property instead.")] | |||
bool TryHarder { get; set; } | |||
/// <summary> | |||
/// Image is a pure monochrome image of a barcode. | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if monochrome image of a barcode; otherwise, <c>false</c>. | |||
/// </value> | |||
[Obsolete("Please use the Options.PureBarcode property instead.")] | |||
bool PureBarcode { get; set; } | |||
/// <summary> | |||
/// Specifies what character encoding to use when decoding, where applicable (type String) | |||
/// </summary> | |||
/// <value> | |||
/// The character set. | |||
/// </value> | |||
[Obsolete("Please use the Options.CharacterSet property instead.")] | |||
string CharacterSet { get; set; } | |||
/// <summary> | |||
/// Image is known to be of one of a few possible formats. | |||
/// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. | |||
/// </summary> | |||
/// <value> | |||
/// The possible formats. | |||
/// </value> | |||
[Obsolete("Please use the Options.PossibleFormats property instead.")] | |||
IList<BarcodeFormat> PossibleFormats { get; set; } | |||
/// <summary> | |||
/// Specifies some options which influence the decoding process | |||
/// </summary> | |||
DecodingOptions Options { get; set; } | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap which is given by a generic byte array. | |||
/// </summary> | |||
/// <param name="rawRGB">The barcode bitmap.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <param name="format">The format.</param> | |||
/// <returns> | |||
/// the result data or null | |||
/// </returns> | |||
Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format); | |||
/// <summary> | |||
/// Tries to decode a barcode within an image which is given by a luminance source. | |||
/// That method gives a chance to prepare a luminance source completely before calling | |||
/// the time consuming decoding method. On the other hand there is a chance to create | |||
/// a luminance source which is independent from external resources (like Bitmap objects) | |||
/// and the decoding call can be made in a background thread. | |||
/// </summary> | |||
/// <param name="luminanceSource">The luminance source.</param> | |||
/// <returns></returns> | |||
Result Decode(LuminanceSource luminanceSource); | |||
#if !PORTABLE | |||
#if !UNITY | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="barcodeBitmap">The barcode bitmap.</param> | |||
/// <returns>the result data or null</returns> | |||
Result Decode(T barcodeBitmap); | |||
#else | |||
/// <summary> | |||
/// Decodes the specified barcode bitmap. | |||
/// </summary> | |||
/// <param name="rawRGB">The barcode bitmap.</param> | |||
/// <returns>the result data or null</returns> | |||
Result Decode(T rawRGB, int width, int height); | |||
#endif | |||
#endif | |||
} | |||
} |
@@ -0,0 +1,314 @@ | |||
/* | |||
* Copyright 2012 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
namespace ZXing | |||
{ | |||
/// <summary> | |||
/// Luminance source class which support different formats of images. | |||
/// </summary> | |||
public partial class RGBLuminanceSource : BaseLuminanceSource | |||
{ | |||
/// <summary> | |||
/// enumeration of supported bitmap format which the RGBLuminanceSource can process | |||
/// </summary> | |||
public enum BitmapFormat | |||
{ | |||
/// <summary> | |||
/// format of the byte[] isn't known. RGBLuminanceSource tries to determine the best possible value | |||
/// </summary> | |||
Unknown, | |||
/// <summary> | |||
/// grayscale array, the byte array is a luminance array with 1 byte per pixel | |||
/// </summary> | |||
Gray8, | |||
/// <summary> | |||
/// 3 bytes per pixel with the channels red, green and blue | |||
/// </summary> | |||
RGB24, | |||
/// <summary> | |||
/// 4 bytes per pixel with the channels red, green and blue | |||
/// </summary> | |||
RGB32, | |||
/// <summary> | |||
/// 4 bytes per pixel with the channels alpha, red, green and blue | |||
/// </summary> | |||
ARGB32, | |||
/// <summary> | |||
/// 3 bytes per pixel with the channels blue, green and red | |||
/// </summary> | |||
BGR24, | |||
/// <summary> | |||
/// 4 bytes per pixel with the channels blue, green and red | |||
/// </summary> | |||
BGR32, | |||
/// <summary> | |||
/// 4 bytes per pixel with the channels blue, green, red and alpha | |||
/// </summary> | |||
BGRA32, | |||
/// <summary> | |||
/// 2 bytes per pixel, 5 bit red, 6 bits green and 5 bits blue | |||
/// </summary> | |||
RGB565, | |||
/// <summary> | |||
/// 4 bytes per pixel with the channels red, green, blue and alpha | |||
/// </summary> | |||
RGBA32, | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class. | |||
/// </summary> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
protected RGBLuminanceSource(int width, int height) | |||
: base(width, height) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class. | |||
/// It supports a byte array with 3 bytes per pixel (RGB24). | |||
/// </summary> | |||
/// <param name="rgbRawBytes">The RGB raw bytes.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height) | |||
: this(rgbRawBytes, width, height, BitmapFormat.RGB24) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class. | |||
/// It supports a byte array with 1 byte per pixel (Gray8). | |||
/// That means the whole array consists of the luminance values (grayscale). | |||
/// </summary> | |||
/// <param name="luminanceArray">The luminance array.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <param name="is8Bit">if set to <c>true</c> [is8 bit].</param> | |||
[Obsolete("Use RGBLuminanceSource(luminanceArray, width, height, BitmapFormat.Gray8)")] | |||
public RGBLuminanceSource(byte[] luminanceArray, int width, int height, bool is8Bit) | |||
: this(luminanceArray, width, height, BitmapFormat.Gray8) | |||
{ | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class. | |||
/// It supports a byte array with 3 bytes per pixel (RGB24). | |||
/// </summary> | |||
/// <param name="rgbRawBytes">The RGB raw bytes.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <param name="bitmapFormat">The bitmap format.</param> | |||
public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height, BitmapFormat bitmapFormat) | |||
: base(width, height) | |||
{ | |||
CalculateLuminance(rgbRawBytes, bitmapFormat); | |||
} | |||
/// <summary> | |||
/// Should create a new luminance source with the right class type. | |||
/// The method is used in methods crop and rotate. | |||
/// </summary> | |||
/// <param name="newLuminances">The new luminances.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <returns></returns> | |||
protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height) | |||
{ | |||
return new RGBLuminanceSource(width, height) { luminances = newLuminances }; | |||
} | |||
private static BitmapFormat DetermineBitmapFormat(byte[] rgbRawBytes, int width, int height) | |||
{ | |||
var square = width*height; | |||
var byteperpixel = rgbRawBytes.Length/square; | |||
switch (byteperpixel) | |||
{ | |||
case 1: | |||
return BitmapFormat.Gray8; | |||
case 2: | |||
return BitmapFormat.RGB565; | |||
case 3: | |||
return BitmapFormat.RGB24; | |||
case 4: | |||
return BitmapFormat.RGB32; | |||
default: | |||
throw new ArgumentException("The bitmap format could not be determined. Please specify the correct value."); | |||
} | |||
} | |||
protected void CalculateLuminance(byte[] rgbRawBytes, BitmapFormat bitmapFormat) | |||
{ | |||
if (bitmapFormat == BitmapFormat.Unknown) | |||
{ | |||
bitmapFormat = DetermineBitmapFormat(rgbRawBytes, Width, Height); | |||
} | |||
switch (bitmapFormat) | |||
{ | |||
case BitmapFormat.Gray8: | |||
Buffer.BlockCopy(rgbRawBytes, 0, luminances, 0, rgbRawBytes.Length < luminances.Length ? rgbRawBytes.Length : luminances.Length); | |||
break; | |||
case BitmapFormat.RGB24: | |||
CalculateLuminanceRGB24(rgbRawBytes); | |||
break; | |||
case BitmapFormat.BGR24: | |||
CalculateLuminanceBGR24(rgbRawBytes); | |||
break; | |||
case BitmapFormat.RGB32: | |||
CalculateLuminanceRGB32(rgbRawBytes); | |||
break; | |||
case BitmapFormat.BGR32: | |||
CalculateLuminanceBGR32(rgbRawBytes); | |||
break; | |||
case BitmapFormat.RGBA32: | |||
CalculateLuminanceRGBA32(rgbRawBytes); | |||
break; | |||
case BitmapFormat.ARGB32: | |||
CalculateLuminanceARGB32(rgbRawBytes); | |||
break; | |||
case BitmapFormat.BGRA32: | |||
CalculateLuminanceBGRA32(rgbRawBytes); | |||
break; | |||
case BitmapFormat.RGB565: | |||
CalculateLuminanceRGB565(rgbRawBytes); | |||
break; | |||
default: | |||
throw new ArgumentException("The bitmap format isn't supported.", bitmapFormat.ToString()); | |||
} | |||
} | |||
private void CalculateLuminanceRGB565(byte[] rgb565RawData) | |||
{ | |||
var luminanceIndex = 0; | |||
for (var index = 0; index < rgb565RawData.Length && luminanceIndex < luminances.Length; index += 2, luminanceIndex++) | |||
{ | |||
var byte1 = rgb565RawData[index]; | |||
var byte2 = rgb565RawData[index + 1]; | |||
var b5 = byte1 & 0x1F; | |||
var g5 = (((byte1 & 0xE0) >> 5) | ((byte2 & 0x03) << 3)) & 0x1F; | |||
var r5 = (byte2 >> 2) & 0x1F; | |||
var r8 = (r5 * 527 + 23) >> 6; | |||
var g8 = (g5 * 527 + 23) >> 6; | |||
var b8 = (b5 * 527 + 23) >> 6; | |||
// cheap, not fully accurate conversion | |||
//var pixel = (byte2 << 8) | byte1; | |||
//b8 = (((pixel) & 0x001F) << 3); | |||
//g8 = (((pixel) & 0x07E0) >> 2) & 0xFF; | |||
//r8 = (((pixel) & 0xF800) >> 8); | |||
luminances[luminanceIndex] = (byte)((RChannelWeight * r8 + GChannelWeight * g8 + BChannelWeight * b8) >> ChannelWeight); | |||
} | |||
} | |||
private void CalculateLuminanceRGB24(byte[] rgbRawBytes) | |||
{ | |||
for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++) | |||
{ | |||
// Calculate luminance cheaply, favoring green. | |||
int r = rgbRawBytes[rgbIndex++]; | |||
int g = rgbRawBytes[rgbIndex++]; | |||
int b = rgbRawBytes[rgbIndex++]; | |||
luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); | |||
} | |||
} | |||
private void CalculateLuminanceBGR24(byte[] rgbRawBytes) | |||
{ | |||
for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++) | |||
{ | |||
// Calculate luminance cheaply, favoring green. | |||
int b = rgbRawBytes[rgbIndex++]; | |||
int g = rgbRawBytes[rgbIndex++]; | |||
int r = rgbRawBytes[rgbIndex++]; | |||
luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); | |||
} | |||
} | |||
private void CalculateLuminanceRGB32(byte[] rgbRawBytes) | |||
{ | |||
for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++) | |||
{ | |||
// Calculate luminance cheaply, favoring green. | |||
int r = rgbRawBytes[rgbIndex++]; | |||
int g = rgbRawBytes[rgbIndex++]; | |||
int b = rgbRawBytes[rgbIndex++]; | |||
rgbIndex++; | |||
luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); | |||
} | |||
} | |||
private void CalculateLuminanceBGR32(byte[] rgbRawBytes) | |||
{ | |||
for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++) | |||
{ | |||
// Calculate luminance cheaply, favoring green. | |||
int b = rgbRawBytes[rgbIndex++]; | |||
int g = rgbRawBytes[rgbIndex++]; | |||
int r = rgbRawBytes[rgbIndex++]; | |||
rgbIndex++; | |||
luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); | |||
} | |||
} | |||
private void CalculateLuminanceBGRA32(byte[] rgbRawBytes) | |||
{ | |||
for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++) | |||
{ | |||
// Calculate luminance cheaply, favoring green. | |||
var b = rgbRawBytes[rgbIndex++]; | |||
var g = rgbRawBytes[rgbIndex++]; | |||
var r = rgbRawBytes[rgbIndex++]; | |||
var alpha = rgbRawBytes[rgbIndex++]; | |||
var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); | |||
luminances[luminanceIndex] = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8)); | |||
} | |||
} | |||
private void CalculateLuminanceRGBA32(byte[] rgbRawBytes) | |||
{ | |||
for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++) | |||
{ | |||
// Calculate luminance cheaply, favoring green. | |||
var r = rgbRawBytes[rgbIndex++]; | |||
var g = rgbRawBytes[rgbIndex++]; | |||
var b = rgbRawBytes[rgbIndex++]; | |||
var alpha = rgbRawBytes[rgbIndex++]; | |||
var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); | |||
luminances[luminanceIndex] = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8)); | |||
} | |||
} | |||
private void CalculateLuminanceARGB32(byte[] rgbRawBytes) | |||
{ | |||
for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++) | |||
{ | |||
// Calculate luminance cheaply, favoring green. | |||
var alpha = rgbRawBytes[rgbIndex++]; | |||
var r = rgbRawBytes[rgbIndex++]; | |||
var g = rgbRawBytes[rgbIndex++]; | |||
var b = rgbRawBytes[rgbIndex++]; | |||
var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); | |||
luminances[luminanceIndex] = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8)); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,128 @@ | |||
/* | |||
* Copyright 2008 ZXing authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
namespace 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> | |||
public sealed class CharacterSetECI : ECI | |||
{ | |||
internal static readonly IDictionary<int, CharacterSetECI> VALUE_TO_ECI; | |||
internal static readonly IDictionary<string, CharacterSetECI> NAME_TO_ECI; | |||
private readonly String encodingName; | |||
public String EncodingName | |||
{ | |||
get | |||
{ | |||
return encodingName; | |||
} | |||
} | |||
static CharacterSetECI() | |||
{ | |||
VALUE_TO_ECI = new Dictionary<int, CharacterSetECI>(); | |||
NAME_TO_ECI = new Dictionary<string, CharacterSetECI>(); | |||
// TODO figure out if these values are even right! | |||
addCharacterSet(0, "CP437"); | |||
addCharacterSet(1, new[] { "ISO-8859-1", "ISO8859_1" }); | |||
addCharacterSet(2, "CP437"); | |||
addCharacterSet(3, new[] { "ISO-8859-1", "ISO8859_1" }); | |||
addCharacterSet(4, new[] { "ISO-8859-2", "ISO8859_2" }); | |||
addCharacterSet(5, new[] { "ISO-8859-3", "ISO8859_3" }); | |||
addCharacterSet(6, new[] { "ISO-8859-4", "ISO8859_4" }); | |||
addCharacterSet(7, new[] { "ISO-8859-5", "ISO8859_5" }); | |||
addCharacterSet(8, new[] { "ISO-8859-6", "ISO8859_6" }); | |||
addCharacterSet(9, new[] { "ISO-8859-7", "ISO8859_7" }); | |||
addCharacterSet(10, new[] { "ISO-8859-8", "ISO8859_8" }); | |||
addCharacterSet(11, new[] { "ISO-8859-9", "ISO8859_9" }); | |||
addCharacterSet(12, new[] { "ISO-8859-4", "ISO-8859-10", "ISO8859_10" }); // use ISO-8859-4 because ISO-8859-16 isn't supported | |||
addCharacterSet(13, new[] { "ISO-8859-11", "ISO8859_11" }); | |||
addCharacterSet(15, new[] { "ISO-8859-13", "ISO8859_13" }); | |||
addCharacterSet(16, new[] { "ISO-8859-1", "ISO-8859-14", "ISO8859_14" }); // use ISO-8859-1 because ISO-8859-16 isn't supported | |||
addCharacterSet(17, new[] { "ISO-8859-15", "ISO8859_15" }); | |||
addCharacterSet(18, new[] { "ISO-8859-3", "ISO-8859-16", "ISO8859_16" }); // use ISO-8859-3 because ISO-8859-16 isn't supported | |||
addCharacterSet(20, new[] { "SJIS", "Shift_JIS" }); | |||
addCharacterSet(21, new[] { "WINDOWS-1250", "CP1250" }); | |||
addCharacterSet(22, new[] { "WINDOWS-1251", "CP1251" }); | |||
addCharacterSet(23, new[] { "WINDOWS-1252", "CP1252" }); | |||
addCharacterSet(24, new[] { "WINDOWS-1256", "CP1256" }); | |||
addCharacterSet(25, new[] { "UTF-16BE", "UNICODEBIG" }); | |||
addCharacterSet(26, new[] { "UTF-8", "UTF8" }); | |||
addCharacterSet(27, "US-ASCII"); | |||
addCharacterSet(170, "US-ASCII"); | |||
addCharacterSet(28, "BIG5"); | |||
addCharacterSet(29, new[] { "GB18030", "GB2312", "EUC_CN", "GBK" }); | |||
addCharacterSet(30, new[] { "EUC-KR", "EUC_KR" }); | |||
} | |||
private CharacterSetECI(int value, String encodingName) | |||
: base(value) | |||
{ | |||
this.encodingName = encodingName; | |||
} | |||
private static void addCharacterSet(int value, String encodingName) | |||
{ | |||
var eci = new CharacterSetECI(value, encodingName); | |||
VALUE_TO_ECI[value] = eci; // can't use valueOf | |||
NAME_TO_ECI[encodingName] = eci; | |||
} | |||
private static void addCharacterSet(int value, String[] encodingNames) | |||
{ | |||
var eci = new CharacterSetECI(value, encodingNames[0]); | |||
VALUE_TO_ECI[value] = eci; // can't use valueOf | |||
foreach (string t in encodingNames) | |||
{ | |||
NAME_TO_ECI[t] = 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) | |||
{ | |||
if (value < 0 || value >= 900) | |||
{ | |||
return null; | |||
} | |||
return VALUE_TO_ECI[value]; | |||
} | |||
/// <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(String name) | |||
{ | |||
return NAME_TO_ECI[name.ToUpper()]; | |||
} | |||
} | |||
} |
@@ -0,0 +1,370 @@ | |||
/* | |||
* Copyright 2013 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel; | |||
namespace ZXing.Common | |||
{ | |||
/// <summary> | |||
/// Defines an container for encoder options | |||
/// </summary> | |||
[Serializable] | |||
public class DecodingOptions | |||
{ | |||
/// <summary> | |||
/// Gets the data container for all options | |||
/// </summary> | |||
[Browsable(false)] | |||
public IDictionary<DecodeHintType, object> Hints { get; private set; } | |||
[field: NonSerialized] | |||
public event Action<object, EventArgs> ValueChanged; | |||
/// <summary> | |||
/// Gets or sets a flag which cause a deeper look into the bitmap | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if [try harder]; otherwise, <c>false</c>. | |||
/// </value> | |||
public bool TryHarder | |||
{ | |||
get | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.TRY_HARDER)) | |||
return (bool)Hints[DecodeHintType.TRY_HARDER]; | |||
return false; | |||
} | |||
set | |||
{ | |||
if (value) | |||
{ | |||
Hints[DecodeHintType.TRY_HARDER] = true; | |||
} | |||
else | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.TRY_HARDER)) | |||
{ | |||
Hints.Remove(DecodeHintType.TRY_HARDER); | |||
} | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Image is a pure monochrome image of a barcode. | |||
/// </summary> | |||
/// <value> | |||
/// <c>true</c> if monochrome image of a barcode; otherwise, <c>false</c>. | |||
/// </value> | |||
public bool PureBarcode | |||
{ | |||
get | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.PURE_BARCODE)) | |||
return (bool)Hints[DecodeHintType.PURE_BARCODE]; | |||
return false; | |||
} | |||
set | |||
{ | |||
if (value) | |||
{ | |||
Hints[DecodeHintType.PURE_BARCODE] = true; | |||
} | |||
else | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.PURE_BARCODE)) | |||
{ | |||
Hints.Remove(DecodeHintType.PURE_BARCODE); | |||
} | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Specifies what character encoding to use when decoding, where applicable (type String) | |||
/// </summary> | |||
/// <value> | |||
/// The character set. | |||
/// </value> | |||
public string CharacterSet | |||
{ | |||
get | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.CHARACTER_SET)) | |||
return (string)Hints[DecodeHintType.CHARACTER_SET]; | |||
return null; | |||
} | |||
set | |||
{ | |||
if (value != null) | |||
{ | |||
Hints[DecodeHintType.CHARACTER_SET] = value; | |||
} | |||
else | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.CHARACTER_SET)) | |||
{ | |||
Hints.Remove(DecodeHintType.CHARACTER_SET); | |||
} | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Image is known to be of one of a few possible formats. | |||
/// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. | |||
/// </summary> | |||
/// <value> | |||
/// The possible formats. | |||
/// </value> | |||
public IList<BarcodeFormat> PossibleFormats | |||
{ | |||
get | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS)) | |||
return (IList<BarcodeFormat>)Hints[DecodeHintType.POSSIBLE_FORMATS]; | |||
return null; | |||
} | |||
set | |||
{ | |||
if (value != null) | |||
{ | |||
Hints[DecodeHintType.POSSIBLE_FORMATS] = value; | |||
} | |||
else | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS)) | |||
{ | |||
Hints.Remove(DecodeHintType.POSSIBLE_FORMATS); | |||
} | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// if Code39 could be detected try to use extended mode for full ASCII character set | |||
/// </summary> | |||
public bool UseCode39ExtendedMode | |||
{ | |||
get | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.USE_CODE_39_EXTENDED_MODE)) | |||
return (bool)Hints[DecodeHintType.USE_CODE_39_EXTENDED_MODE]; | |||
return false; | |||
} | |||
set | |||
{ | |||
if (value) | |||
{ | |||
Hints[DecodeHintType.USE_CODE_39_EXTENDED_MODE] = true; | |||
} | |||
else | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.USE_CODE_39_EXTENDED_MODE)) | |||
{ | |||
Hints.Remove(DecodeHintType.USE_CODE_39_EXTENDED_MODE); | |||
} | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Don't fail if a Code39 is detected but can't be decoded in extended mode. | |||
/// Return the raw Code39 result instead. Maps to <see cref="bool" />. | |||
/// </summary> | |||
public bool UseCode39RelaxedExtendedMode | |||
{ | |||
get | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE)) | |||
return (bool)Hints[DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE]; | |||
return false; | |||
} | |||
set | |||
{ | |||
if (value) | |||
{ | |||
Hints[DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE] = true; | |||
} | |||
else | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE)) | |||
{ | |||
Hints.Remove(DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE); | |||
} | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// If true, return the start and end digits in a Codabar barcode instead of stripping them. They | |||
/// are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them | |||
/// to not be. Doesn't matter what it maps to; use <see cref="bool" />. | |||
/// </summary> | |||
public bool ReturnCodabarStartEnd | |||
{ | |||
get | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.RETURN_CODABAR_START_END)) | |||
return (bool)Hints[DecodeHintType.RETURN_CODABAR_START_END]; | |||
return false; | |||
} | |||
set | |||
{ | |||
if (value) | |||
{ | |||
Hints[DecodeHintType.RETURN_CODABAR_START_END] = true; | |||
} | |||
else | |||
{ | |||
if (Hints.ContainsKey(DecodeHintType.RETURN_CODABAR_START_END)) | |||
{ | |||
Hints.Remove(DecodeHintType.RETURN_CODABAR_START_END); | |||
} | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="EncodingOptions"/> class. | |||
/// </summary> | |||
public DecodingOptions() | |||
{ | |||
var hints = new ChangeNotifyDictionary<DecodeHintType, object>(); | |||
Hints = hints; | |||
UseCode39ExtendedMode = true; | |||
UseCode39RelaxedExtendedMode = true; | |||
hints.ValueChanged += (o, args) => { if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); }; | |||
} | |||
[Serializable] | |||
private class ChangeNotifyDictionary<TKey, TValue>: IDictionary<TKey, TValue> | |||
{ | |||
private readonly IDictionary<TKey, TValue> values; | |||
[field: NonSerialized] | |||
public event Action<object, EventArgs> ValueChanged; | |||
public ChangeNotifyDictionary() | |||
{ | |||
values = new Dictionary<TKey, TValue>(); | |||
} | |||
private void OnValueChanged() | |||
{ | |||
if (ValueChanged != null) | |||
ValueChanged(this, EventArgs.Empty); | |||
} | |||
public void Add(TKey key, TValue value) | |||
{ | |||
values.Add(key, value); | |||
OnValueChanged(); | |||
} | |||
public bool ContainsKey(TKey key) | |||
{ | |||
return values.ContainsKey(key); | |||
} | |||
public ICollection<TKey> Keys | |||
{ | |||
get { return values.Keys; } | |||
} | |||
public bool Remove(TKey key) | |||
{ | |||
var result = values.Remove(key); | |||
OnValueChanged(); | |||
return result; | |||
} | |||
public bool TryGetValue(TKey key, out TValue value) | |||
{ | |||
return values.TryGetValue(key, out value); | |||
} | |||
public ICollection<TValue> Values | |||
{ | |||
get { return values.Values; } | |||
} | |||
public TValue this[TKey key] | |||
{ | |||
get | |||
{ | |||
return values[key]; | |||
} | |||
set | |||
{ | |||
values[key] = value; | |||
OnValueChanged(); | |||
} | |||
} | |||
public void Add(KeyValuePair<TKey, TValue> item) | |||
{ | |||
values.Add(item); | |||
OnValueChanged(); | |||
} | |||
public void Clear() | |||
{ | |||
values.Clear(); | |||
OnValueChanged(); | |||
} | |||
public bool Contains(KeyValuePair<TKey, TValue> item) | |||
{ | |||
return values.Contains(item); | |||
} | |||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) | |||
{ | |||
values.CopyTo(array, arrayIndex); | |||
} | |||
public int Count | |||
{ | |||
get { return values.Count; } | |||
} | |||
public bool IsReadOnly | |||
{ | |||
get { return values.IsReadOnly; } | |||
} | |||
public bool Remove(KeyValuePair<TKey, TValue> item) | |||
{ | |||
var result = values.Remove(item); | |||
OnValueChanged(); | |||
return result; | |||
} | |||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() | |||
{ | |||
return values.GetEnumerator(); | |||
} | |||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | |||
{ | |||
return ((System.Collections.IEnumerable)values).GetEnumerator(); | |||
} | |||
} | |||
} | |||
} |
@@ -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 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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,243 @@ | |||
/* | |||
* Copyright 2009 ZXing authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
namespace 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. | |||
/// | |||
/// <author>dswitkin@google.com (Daniel Switkin)</author> | |||
/// <author>Sean Owen</author> | |||
/// </summary> | |||
public class GlobalHistogramBinarizer : Binarizer | |||
{ | |||
private const int LUMINANCE_BITS = 5; | |||
private const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS; | |||
private const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS; | |||
private static readonly byte[] EMPTY = new byte[0]; | |||
private byte[] luminances; | |||
private readonly int[] buckets; | |||
/// <summary> | |||
/// Initializes a new instance of the <see cref="GlobalHistogramBinarizer"/> class. | |||
/// </summary> | |||
/// <param name="source">The source.</param> | |||
public GlobalHistogramBinarizer(LuminanceSource source) | |||
: base(source) | |||
{ | |||
luminances = EMPTY; | |||
buckets = new int[LUMINANCE_BUCKETS]; | |||
} | |||
/// <summary> | |||
/// Applies simple sharpening to the row data to improve performance of the 1D Readers. | |||
/// </summary> | |||
/// <param name="y"></param> | |||
/// <param name="row"></param> | |||
/// <returns></returns> | |||
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); | |||
byte[] 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; | |||
if (!estimateBlackPoint(localBuckets, out blackPoint)) | |||
return null; | |||
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; | |||
row[x] = (luminance < blackPoint); | |||
left = center; | |||
center = right; | |||
} | |||
return row; | |||
} | |||
/// <summary> | |||
/// Does not sharpen the data, as this call is intended to only be used by 2D Readers. | |||
/// </summary> | |||
override public BitMatrix BlackMatrix | |||
{ | |||
get | |||
{ | |||
LuminanceSource source = LuminanceSource; | |||
byte[] localLuminances; | |||
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; | |||
localLuminances = source.getRow(row, luminances); | |||
int right = (width << 2) / 5; | |||
for (int x = width / 5; x < right; x++) | |||
{ | |||
int pixel = localLuminances[x] & 0xff; | |||
localBuckets[pixel >> LUMINANCE_SHIFT]++; | |||
} | |||
} | |||
int blackPoint; | |||
if (!estimateBlackPoint(localBuckets, out blackPoint)) | |||
return null; | |||
// 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; | |||
for (int y = 0; y < height; y++) | |||
{ | |||
int offset = y * width; | |||
for (int x = 0; x < width; x++) | |||
{ | |||
int pixel = localLuminances[offset + x] & 0xff; | |||
matrix[x, y] = (pixel < blackPoint); | |||
} | |||
} | |||
return matrix; | |||
} | |||
} | |||
/// <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 override Binarizer createBinarizer(LuminanceSource source) | |||
{ | |||
return new GlobalHistogramBinarizer(source); | |||
} | |||
private void initArrays(int luminanceSize) | |||
{ | |||
if (luminances.Length < luminanceSize) | |||
{ | |||
luminances = new byte[luminanceSize]; | |||
} | |||
for (int x = 0; x < LUMINANCE_BUCKETS; x++) | |||
{ | |||
buckets[x] = 0; | |||
} | |||
} | |||
private static bool estimateBlackPoint(int[] buckets, out int blackPoint) | |||
{ | |||
blackPoint = 0; | |||
// 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) | |||
{ | |||
return false; | |||
} | |||
// 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; | |||
} | |||
} | |||
blackPoint = bestValley << LUMINANCE_SHIFT; | |||
return true; | |||
} | |||
} | |||
} |
@@ -0,0 +1,288 @@ | |||
/* | |||
* Copyright 2009 ZXing authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
namespace 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 BLOCK_SIZE_POWER = 3; | |||
private const int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER; // ...0100...00 | |||
private const int BLOCK_SIZE_MASK = BLOCK_SIZE - 1; // ...0011...11 | |||
private const int MINIMUM_DIMENSION = 40; | |||
private const int MIN_DYNAMIC_RANGE = 24; | |||
private BitMatrix matrix = null; | |||
public HybridBinarizer(LuminanceSource source) | |||
: base(source) | |||
{ | |||
} | |||
public override Binarizer createBinarizer(LuminanceSource source) | |||
{ | |||
return new HybridBinarizer(source); | |||
} | |||
/// <summary> | |||
/// Calculates the final BitMatrix once for all requests. This could be called once from the | |||
/// constructor instead, but there are some advantages to doing it lazily, such as making | |||
/// profiling easier, and not doing heavy lifting when callers don't expect it. | |||
/// </summary> | |||
private void binarizeEntireImage() | |||
{ | |||
if (matrix == null) | |||
{ | |||
LuminanceSource source = LuminanceSource; | |||
int width = source.Width; | |||
int height = source.Height; | |||
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) | |||
{ | |||
byte[] luminances = source.Matrix; | |||
int subWidth = width >> BLOCK_SIZE_POWER; | |||
if ((width & BLOCK_SIZE_MASK) != 0) | |||
{ | |||
subWidth++; | |||
} | |||
int subHeight = height >> BLOCK_SIZE_POWER; | |||
if ((height & BLOCK_SIZE_MASK) != 0) | |||
{ | |||
subHeight++; | |||
} | |||
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height); | |||
var newMatrix = new BitMatrix(width, height); | |||
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix); | |||
matrix = newMatrix; | |||
} | |||
else | |||
{ | |||
// If the image is too small, fall back to the global histogram approach. | |||
matrix = base.BlackMatrix; | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// 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 (fractional blocks are computed based | |||
/// on the last 8 pixels in the row/column which are also used in the previous block). | |||
/// </summary> | |||
/// <param name="luminances">The luminances.</param> | |||
/// <param name="subWidth">Width of the sub.</param> | |||
/// <param name="subHeight">Height of the sub.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <param name="blackPoints">The black points.</param> | |||
/// <param name="matrix">The matrix.</param> | |||
private static void calculateThresholdForBlock(byte[] luminances, int subWidth, int subHeight, int width, int height, int[][] blackPoints, BitMatrix matrix) | |||
{ | |||
for (int y = 0; y < subHeight; y++) | |||
{ | |||
int yoffset = y << BLOCK_SIZE_POWER; | |||
int maxYOffset = height - BLOCK_SIZE; | |||
if (yoffset > maxYOffset) | |||
{ | |||
yoffset = maxYOffset; | |||
} | |||
for (int x = 0; x < subWidth; x++) | |||
{ | |||
int xoffset = x << BLOCK_SIZE_POWER; | |||
int maxXOffset = width - BLOCK_SIZE; | |||
if (xoffset > maxXOffset) | |||
{ | |||
xoffset = maxXOffset; | |||
} | |||
int left = cap(x, 2, subWidth - 3); | |||
int top = cap(y, 2, subHeight - 3); | |||
int sum = 0; | |||
for (int z = -2; z <= 2; z++) | |||
{ | |||
int[] blackRow = blackPoints[top + z]; | |||
sum += blackRow[left - 2]; | |||
sum += blackRow[left - 1]; | |||
sum += blackRow[left]; | |||
sum += blackRow[left + 1]; | |||
sum += blackRow[left + 2]; | |||
} | |||
int average = sum / 25; | |||
thresholdBlock(luminances, xoffset, yoffset, average, width, matrix); | |||
} | |||
} | |||
} | |||
private static int cap(int value, int min, int max) | |||
{ | |||
return value < min ? min : value > max ? max : value; | |||
} | |||
/// <summary> | |||
/// Applies a single threshold to an 8x8 block of pixels. | |||
/// </summary> | |||
/// <param name="luminances">The luminances.</param> | |||
/// <param name="xoffset">The xoffset.</param> | |||
/// <param name="yoffset">The yoffset.</param> | |||
/// <param name="threshold">The threshold.</param> | |||
/// <param name="stride">The stride.</param> | |||
/// <param name="matrix">The matrix.</param> | |||
private static void thresholdBlock(byte[] luminances, int xoffset, int yoffset, int threshold, int stride, BitMatrix matrix) | |||
{ | |||
int offset = (yoffset * stride) + xoffset; | |||
for (int y = 0; y < BLOCK_SIZE; y++, offset += stride) | |||
{ | |||
for (int x = 0; x < BLOCK_SIZE; x++) | |||
{ | |||
int pixel = luminances[offset + x] & 0xff; | |||
// Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0. | |||
matrix[xoffset + x, yoffset + y] = (pixel <= threshold); | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// Calculates a single black point for each 8x8 block of pixels and saves it away. | |||
/// See the following thread for a discussion of this algorithm: | |||
/// http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0 | |||
/// </summary> | |||
/// <param name="luminances">The luminances.</param> | |||
/// <param name="subWidth">Width of the sub.</param> | |||
/// <param name="subHeight">Height of the sub.</param> | |||
/// <param name="width">The width.</param> | |||
/// <param name="height">The height.</param> | |||
/// <returns></returns> | |||
private static int[][] calculateBlackPoints(byte[] luminances, int subWidth, int subHeight, int width, int height) | |||
{ | |||
int[][] blackPoints = new int[subHeight][]; | |||
for (int i = 0; i < subHeight; i++) | |||
{ | |||
blackPoints[i] = new int[subWidth]; | |||
} | |||
for (int y = 0; y < subHeight; y++) | |||
{ | |||
int yoffset = y << BLOCK_SIZE_POWER; | |||
int maxYOffset = height - BLOCK_SIZE; | |||
if (yoffset > maxYOffset) | |||
{ | |||
yoffset = maxYOffset; | |||
} | |||
for (int x = 0; x < subWidth; x++) | |||
{ | |||
int xoffset = x << BLOCK_SIZE_POWER; | |||
int maxXOffset = width - BLOCK_SIZE; | |||
if (xoffset > maxXOffset) | |||
{ | |||
xoffset = maxXOffset; | |||
} | |||
int sum = 0; | |||
int min = 0xFF; | |||
int max = 0; | |||
for (int yy = 0, offset = yoffset * width + xoffset; yy < BLOCK_SIZE; yy++, offset += width) | |||
{ | |||
for (int xx = 0; xx < BLOCK_SIZE; xx++) | |||
{ | |||
int pixel = luminances[offset + xx] & 0xFF; | |||
// still looking for good contrast | |||
sum += pixel; | |||
if (pixel < min) | |||
{ | |||
min = pixel; | |||
} | |||
if (pixel > max) | |||
{ | |||
max = pixel; | |||
} | |||
} | |||
// short-circuit min/max tests once dynamic range is met | |||
if (max - min > MIN_DYNAMIC_RANGE) | |||
{ | |||
// finish the rest of the rows quickly | |||
for (yy++, offset += width; yy < BLOCK_SIZE; yy++, offset += width) | |||
{ | |||
for (int xx = 0; xx < BLOCK_SIZE; xx++) | |||
{ | |||
sum += luminances[offset + xx] & 0xFF; | |||
} | |||
} | |||
} | |||
} | |||
// The default estimate is the average of the values in the block. | |||
int average = sum >> (BLOCK_SIZE_POWER * 2); | |||
if (max - min <= MIN_DYNAMIC_RANGE) | |||
{ | |||
// If variation within the block is low, assume this is a block with only light or only | |||
// dark pixels. In that case we do not want to use the average, as it would divide this | |||
// low contrast area into black and white pixels, essentially creating data out of noise. | |||
// | |||
// The default assumption is that the block is light/background. Since no estimate for | |||
// the level of dark pixels exists locally, use half the min for the block. | |||
average = min >> 1; | |||
if (y > 0 && x > 0) | |||
{ | |||
// Correct the "white background" assumption for blocks that have neighbors by comparing | |||
// the pixels in this block to the previously calculated black points. This is based on | |||
// the fact that dark barcode symbology is always surrounded by some amount of light | |||
// background for which reasonable black point estimates were made. The bp estimated at | |||
// the boundaries is used for the interior. | |||
// The (min < bp) is arbitrary but works better than other heuristics that were tried. | |||
int averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + | |||
blackPoints[y - 1][x - 1]) >> 2; | |||
if (min < averageNeighborBlackPoint) | |||
{ | |||
average = averageNeighborBlackPoint; | |||
} | |||
} | |||
} | |||
blackPoints[y][x] = average; | |||
} | |||
} | |||
return blackPoints; | |||
} | |||
} | |||
} |
@@ -0,0 +1,266 @@ | |||
/* | |||
* Copyright (C) 2010 ZXing authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace ZXing.Common | |||
{ | |||
/// <summary> | |||
/// Common string-related functions. | |||
/// </summary> | |||
/// <author>Sean Owen</author> | |||
/// <author>Alex Dupre</author> | |||
public static class StringUtils | |||
{ | |||
#if (WINDOWS_PHONE70 || WINDOWS_PHONE71 || WINDOWS_PHONE80 || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE) | |||
private const String PLATFORM_DEFAULT_ENCODING = "UTF-8"; | |||
#else | |||
private static String PLATFORM_DEFAULT_ENCODING = Encoding.Default.WebName; | |||
#endif | |||
public static String SHIFT_JIS = "SJIS"; | |||
public static String GB2312 = "GB2312"; | |||
private const String EUC_JP = "EUC-JP"; | |||
private const String UTF8 = "UTF-8"; | |||
private const String ISO88591 = "ISO-8859-1"; | |||
private static readonly bool ASSUME_SHIFT_JIS = | |||
String.Compare(SHIFT_JIS, PLATFORM_DEFAULT_ENCODING, StringComparison.OrdinalIgnoreCase) == 0 || | |||
String.Compare(EUC_JP, PLATFORM_DEFAULT_ENCODING, StringComparison.OrdinalIgnoreCase) == 0; | |||
/// <summary> | |||
/// Guesses the encoding. | |||
/// </summary> | |||
/// <param name="bytes">bytes encoding a string, whose encoding should be guessed</param> | |||
/// <param name="hints">decode hints if applicable</param> | |||
/// <returns>name of guessed encoding; at the moment will only guess one of: | |||
/// {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform | |||
/// default encoding if none of these can possibly be correct</returns> | |||
public static String guessEncoding(byte[] bytes, IDictionary<DecodeHintType, object> hints) | |||
{ | |||
if (hints != null && hints.ContainsKey(DecodeHintType.CHARACTER_SET)) | |||
{ | |||
String characterSet = (String)hints[DecodeHintType.CHARACTER_SET]; | |||
if (characterSet != null) | |||
{ | |||
return characterSet; | |||
} | |||
} | |||
// For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS, | |||
// which should be by far the most common encodings. | |||
int length = bytes.Length; | |||
bool canBeISO88591 = true; | |||
bool canBeShiftJIS = true; | |||
bool canBeUTF8 = true; | |||
int utf8BytesLeft = 0; | |||
//int utf8LowChars = 0; | |||
int utf2BytesChars = 0; | |||
int utf3BytesChars = 0; | |||
int utf4BytesChars = 0; | |||
int sjisBytesLeft = 0; | |||
//int sjisLowChars = 0; | |||
int sjisKatakanaChars = 0; | |||
//int sjisDoubleBytesChars = 0; | |||
int sjisCurKatakanaWordLength = 0; | |||
int sjisCurDoubleBytesWordLength = 0; | |||
int sjisMaxKatakanaWordLength = 0; | |||
int sjisMaxDoubleBytesWordLength = 0; | |||
//int isoLowChars = 0; | |||
//int isoHighChars = 0; | |||
int isoHighOther = 0; | |||
bool utf8bom = bytes.Length > 3 && | |||
bytes[0] == 0xEF && | |||
bytes[1] == 0xBB && | |||
bytes[2] == 0xBF; | |||
for (int i = 0; | |||
i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8); | |||
i++) | |||
{ | |||
int value = bytes[i] & 0xFF; | |||
// UTF-8 stuff | |||
if (canBeUTF8) | |||
{ | |||
if (utf8BytesLeft > 0) | |||
{ | |||
if ((value & 0x80) == 0) | |||
{ | |||
canBeUTF8 = false; | |||
} | |||
else | |||
{ | |||
utf8BytesLeft--; | |||
} | |||
} | |||
else if ((value & 0x80) != 0) | |||
{ | |||
if ((value & 0x40) == 0) | |||
{ | |||
canBeUTF8 = false; | |||
} | |||
else | |||
{ | |||
utf8BytesLeft++; | |||
if ((value & 0x20) == 0) | |||
{ | |||
utf2BytesChars++; | |||
} | |||
else | |||
{ | |||
utf8BytesLeft++; | |||
if ((value & 0x10) == 0) | |||
{ | |||
utf3BytesChars++; | |||
} | |||
else | |||
{ | |||
utf8BytesLeft++; | |||
if ((value & 0x08) == 0) | |||
{ | |||
utf4BytesChars++; | |||
} | |||
else | |||
{ | |||
canBeUTF8 = false; | |||
} | |||
} | |||
} | |||
} | |||
} //else { | |||
//utf8LowChars++; | |||
//} | |||
} | |||
// ISO-8859-1 stuff | |||
if (canBeISO88591) | |||
{ | |||
if (value > 0x7F && value < 0xA0) | |||
{ | |||
canBeISO88591 = false; | |||
} | |||
else if (value > 0x9F) | |||
{ | |||
if (value < 0xC0 || value == 0xD7 || value == 0xF7) | |||
{ | |||
isoHighOther++; | |||
} //else { | |||
//isoHighChars++; | |||
//} | |||
} //else { | |||
//isoLowChars++; | |||
//} | |||
} | |||
// Shift_JIS stuff | |||
if (canBeShiftJIS) | |||
{ | |||
if (sjisBytesLeft > 0) | |||
{ | |||
if (value < 0x40 || value == 0x7F || value > 0xFC) | |||
{ | |||
canBeShiftJIS = false; | |||
} | |||
else | |||
{ | |||
sjisBytesLeft--; | |||
} | |||
} | |||
else if (value == 0x80 || value == 0xA0 || value > 0xEF) | |||
{ | |||
canBeShiftJIS = false; | |||
} | |||
else if (value > 0xA0 && value < 0xE0) | |||
{ | |||
sjisKatakanaChars++; | |||
sjisCurDoubleBytesWordLength = 0; | |||
sjisCurKatakanaWordLength++; | |||
if (sjisCurKatakanaWordLength > sjisMaxKatakanaWordLength) | |||
{ | |||
sjisMaxKatakanaWordLength = sjisCurKatakanaWordLength; | |||
} | |||
} | |||
else if (value > 0x7F) | |||
{ | |||
sjisBytesLeft++; | |||
//sjisDoubleBytesChars++; | |||
sjisCurKatakanaWordLength = 0; | |||
sjisCurDoubleBytesWordLength++; | |||
if (sjisCurDoubleBytesWordLength > sjisMaxDoubleBytesWordLength) | |||
{ | |||
sjisMaxDoubleBytesWordLength = sjisCurDoubleBytesWordLength; | |||
} | |||
} | |||
else | |||
{ | |||
//sjisLowChars++; | |||
sjisCurKatakanaWordLength = 0; | |||
sjisCurDoubleBytesWordLength = 0; | |||
} | |||
} | |||
} | |||
if (canBeUTF8 && utf8BytesLeft > 0) | |||
{ | |||
canBeUTF8 = false; | |||
} | |||
if (canBeShiftJIS && sjisBytesLeft > 0) | |||
{ | |||
canBeShiftJIS = false; | |||
} | |||
// Easy -- if there is BOM or at least 1 valid not-single byte character (and no evidence it can't be UTF-8), done | |||
if (canBeUTF8 && (utf8bom || utf2BytesChars + utf3BytesChars + utf4BytesChars > 0)) | |||
{ | |||
return UTF8; | |||
} | |||
// Easy -- if assuming Shift_JIS or at least 3 valid consecutive not-ascii characters (and no evidence it can't be), done | |||
if (canBeShiftJIS && (ASSUME_SHIFT_JIS || sjisMaxKatakanaWordLength >= 3 || sjisMaxDoubleBytesWordLength >= 3)) | |||
{ | |||
return SHIFT_JIS; | |||
} | |||
// Distinguishing Shift_JIS and ISO-8859-1 can be a little tough for short words. The crude heuristic is: | |||
// - If we saw | |||
// - only two consecutive katakana chars in the whole text, or | |||
// - at least 10% of bytes that could be "upper" not-alphanumeric Latin1, | |||
// - then we conclude Shift_JIS, else ISO-8859-1 | |||
if (canBeISO88591 && canBeShiftJIS) | |||
{ | |||
return (sjisMaxKatakanaWordLength == 2 && sjisKatakanaChars == 2) || isoHighOther * 10 >= length | |||
? SHIFT_JIS : ISO88591; | |||
} | |||
// Otherwise, try in order ISO-8859-1, Shift JIS, UTF-8 and fall back to default platform encoding | |||
if (canBeISO88591) | |||
{ | |||
return ISO88591; | |||
} | |||
if (canBeShiftJIS) | |||
{ | |||
return SHIFT_JIS; | |||
} | |||
if (canBeUTF8) | |||
{ | |||
return UTF8; | |||
} | |||
// Otherwise, we take a wild guess with platform encoding | |||
return PLATFORM_DEFAULT_ENCODING; | |||
} | |||
} | |||
} |
@@ -0,0 +1,102 @@ | |||
/* | |||
* Copyright 2013 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
namespace ZXing | |||
{ | |||
#if !WindowsCE | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
public delegate void Action(); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
public delegate void Action<in T1>(T1 param1); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
public delegate void Action<in T1, in T2>(T1 param1, T2 param2); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
public delegate void Action<in T1, in T2, in T3>(T1 param1, T2 param2, T3 param3); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <typeparam name="T4">The type of the 4.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
/// <param name="param4">The param4.</param> | |||
public delegate void Action<in T1, in T2, in T3, in T4>(T1 param1, T2 param2, T3 param3, T4 param4); | |||
#else | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
public delegate void Action(); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
public delegate void Action<T1>(T1 param1); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
public delegate void Action<T1, T2>(T1 param1, T2 param2); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
public delegate void Action<T1, T2, T3>(T1 param1, T2 param2, T3 param3); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <typeparam name="T4">The type of the 4.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
/// <param name="param4">The param4.</param> | |||
public delegate void Action<T1, T2, T3, T4>(T1 param1, T2 param2, T3 param3, T4 param4); | |||
#endif | |||
} |
@@ -0,0 +1,122 @@ | |||
/* | |||
* Copyright 2012 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
namespace ZXing | |||
{ | |||
#if !WindowsCE | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <returns></returns> | |||
public delegate TResult Func<out TResult>(); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<in T1, out TResult>(T1 param1); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<in T1, in T2, out TResult>(T1 param1, T2 param2); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<in T1, in T2, in T3, out TResult>(T1 param1, T2 param2, T3 param3); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <typeparam name="T4">The type of the 4.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
/// <param name="param4">The param4.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<in T1, in T2, in T3, in T4, out TResult>(T1 param1, T2 param2, T3 param3, T4 param4); | |||
#else | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <returns></returns> | |||
public delegate TResult Func<TResult>(); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<T1, TResult>(T1 param1); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<T1, T2, TResult>(T1 param1, T2 param2); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<T1, T2, T3, TResult>(T1 param1, T2 param2, T3 param3); | |||
/// <summary> | |||
/// for compatibility with .net 4.0 | |||
/// </summary> | |||
/// <typeparam name="T1">The type of the 1.</typeparam> | |||
/// <typeparam name="T2">The type of the 2.</typeparam> | |||
/// <typeparam name="T3">The type of the 3.</typeparam> | |||
/// <typeparam name="T4">The type of the 4.</typeparam> | |||
/// <typeparam name="TResult">The type of the result.</typeparam> | |||
/// <param name="param1">The param1.</param> | |||
/// <param name="param2">The param2.</param> | |||
/// <param name="param3">The param3.</param> | |||
/// <param name="param4">The param4.</param> | |||
/// <returns></returns> | |||
public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 param1, T2 param2, T3 param3, T4 param4); | |||
#endif | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* Copyright 2012 ZXing.Net authors | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
namespace System | |||
{ | |||
internal class TimeZoneInfo | |||
{ | |||
internal static TimeZoneInfo Local = null; | |||
internal static DateTime ConvertTime(DateTime dateTime, TimeZoneInfo destinationTimeZone) | |||
{ | |||
// TODO: fix it for .net 2.0 | |||
return dateTime; | |||
} | |||
} | |||
} |
@@ -54,7 +54,7 @@ namespace ZXing.QrCode.Internal | |||
try | |||
{ | |||
//CharacterSetECI currentCharacterSetECI = null; | |||
CharacterSetECI currentCharacterSetECI = null; | |||
bool fc1InEffect = false; | |||
Mode mode; | |||
do | |||
@@ -94,14 +94,29 @@ namespace ZXing.QrCode.Internal | |||
symbolSequence = bits.readBits(8); | |||
parityData = bits.readBits(8); | |||
} | |||
else if (mode == Mode.ECI) | |||
{ | |||
// Count doesn't apply to ECI | |||
int value = parseECIValue(bits); | |||
currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value); | |||
if (currentCharacterSetECI == null) | |||
{ | |||
return null; | |||
} | |||
} | |||
else | |||
{ | |||
// First handle Hanzi mode which does not start with character count | |||
if (mode == Mode.HANZI) | |||
{ | |||
//chinese mode contains a sub set indicator right after mode indicator | |||
//int subset = bits.readBits(4); | |||
//int countHanzi = bits.readBits(mode.getCharacterCountBits(version)); | |||
int subset = bits.readBits(4); | |||
int countHanzi = bits.readBits(mode.getCharacterCountBits(version)); | |||
if (subset == GB2312_SUBSET) | |||
{ | |||
if (!decodeHanziSegment(bits, result, countHanzi)) | |||
return null; | |||
} | |||
} | |||
else | |||
{ | |||
@@ -118,6 +133,16 @@ namespace ZXing.QrCode.Internal | |||
if (!decodeAlphanumericSegment(bits, result, count, fc1InEffect)) | |||
return null; | |||
} | |||
else if (mode == Mode.BYTE) | |||
{ | |||
if (!decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints)) | |||
return null; | |||
} | |||
else if (mode == Mode.KANJI) | |||
{ | |||
if (!decodeKanjiSegment(bits, result, count)) | |||
return null; | |||
} | |||
else | |||
{ | |||
return null; | |||
@@ -145,8 +170,214 @@ namespace ZXing.QrCode.Internal | |||
symbolSequence, parityData); | |||
} | |||
/// <summary> | |||
/// See specification GBT 18284-2000 | |||
/// </summary> | |||
/// <param name="bits">The bits.</param> | |||
/// <param name="result">The result.</param> | |||
/// <param name="count">The count.</param> | |||
/// <returns></returns> | |||
private static bool decodeHanziSegment(BitSource bits, | |||
StringBuilder result, | |||
int count) | |||
{ | |||
// Don't crash trying to read more bits than we have available. | |||
if (count * 13 > bits.available()) | |||
{ | |||
return false; | |||
} | |||
// Each character will require 2 bytes. Read the characters as 2-byte pairs | |||
// and decode as GB2312 afterwards | |||
byte[] buffer = new byte[2 * count]; | |||
int offset = 0; | |||
while (count > 0) | |||
{ | |||
// Each 13 bits encodes a 2-byte character | |||
int twoBytes = bits.readBits(13); | |||
int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060); | |||
if (assembledTwoBytes < 0x003BF) | |||
{ | |||
// In the 0xA1A1 to 0xAAFE range | |||
assembledTwoBytes += 0x0A1A1; | |||
} | |||
else | |||
{ | |||
// In the 0xB0A1 to 0xFAFE range | |||
assembledTwoBytes += 0x0A6A1; | |||
} | |||
buffer[offset] = (byte)((assembledTwoBytes >> 8) & 0xFF); | |||
buffer[offset + 1] = (byte)(assembledTwoBytes & 0xFF); | |||
offset += 2; | |||
count--; | |||
} | |||
try | |||
{ | |||
result.Append(Encoding.GetEncoding(StringUtils.GB2312).GetString(buffer, 0, buffer.Length)); | |||
} | |||
#if (WINDOWS_PHONE70 || WINDOWS_PHONE71 || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || MONOANDROID || MONOTOUCH) | |||
catch (ArgumentException) | |||
{ | |||
try | |||
{ | |||
// Silverlight only supports a limited number of character sets, trying fallback to UTF-8 | |||
result.Append(Encoding.GetEncoding("UTF-8").GetString(buffer, 0, buffer.Length)); | |||
} | |||
catch (Exception) | |||
{ | |||
return false; | |||
} | |||
} | |||
#endif | |||
catch (Exception) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
private static bool decodeKanjiSegment(BitSource bits, | |||
StringBuilder result, | |||
int count) | |||
{ | |||
// Don't crash trying to read more bits than we have available. | |||
if (count * 13 > bits.available()) | |||
{ | |||
return false; | |||
} | |||
// Each character will require 2 bytes. Read the characters as 2-byte pairs | |||
// and decode as Shift_JIS afterwards | |||
byte[] buffer = new byte[2 * count]; | |||
int offset = 0; | |||
while (count > 0) | |||
{ | |||
// Each 13 bits encodes a 2-byte character | |||
int twoBytes = bits.readBits(13); | |||
int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0); | |||
if (assembledTwoBytes < 0x01F00) | |||
{ | |||
// In the 0x8140 to 0x9FFC range | |||
assembledTwoBytes += 0x08140; | |||
} | |||
else | |||
{ | |||
// In the 0xE040 to 0xEBBF range | |||
assembledTwoBytes += 0x0C140; | |||
} | |||
buffer[offset] = (byte)(assembledTwoBytes >> 8); | |||
buffer[offset + 1] = (byte)assembledTwoBytes; | |||
offset += 2; | |||
count--; | |||
} | |||
// Shift_JIS may not be supported in some environments: | |||
try | |||
{ | |||
result.Append(Encoding.GetEncoding(StringUtils.SHIFT_JIS).GetString(buffer, 0, buffer.Length)); | |||
} | |||
#if (WINDOWS_PHONE70 || WINDOWS_PHONE71 || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || MONOANDROID || MONOTOUCH) | |||
catch (ArgumentException) | |||
{ | |||
try | |||
{ | |||
// Silverlight only supports a limited number of character sets, trying fallback to UTF-8 | |||
result.Append(Encoding.GetEncoding("UTF-8").GetString(buffer, 0, buffer.Length)); | |||
} | |||
catch (Exception) | |||
{ | |||
return false; | |||
} | |||
} | |||
#endif | |||
catch (Exception) | |||
{ | |||
return false; | |||
} | |||
return true; | |||
} | |||
private static bool decodeByteSegment(BitSource bits, | |||
StringBuilder result, | |||
int count, | |||
CharacterSetECI currentCharacterSetECI, | |||
IList<byte[]> byteSegments, | |||
IDictionary<DecodeHintType, object> hints) | |||
{ | |||
// Don't crash trying to read more bits than we have available. | |||
if (count << 3 > bits.available()) | |||
{ | |||
return false; | |||
} | |||
byte[] readBytes = new byte[count]; | |||
for (int i = 0; i < count; i++) | |||
{ | |||
readBytes[i] = (byte)bits.readBits(8); | |||
} | |||
String encoding; | |||
if (currentCharacterSetECI == null) | |||
{ | |||
// The spec isn't clear on this mode; see | |||
// section 6.4.5: t does not say which encoding to assuming | |||
// upon decoding. I have seen ISO-8859-1 used as well as | |||
// Shift_JIS -- without anything like an ECI designator to | |||
// give a hint. | |||
encoding = StringUtils.guessEncoding(readBytes, hints); | |||
} | |||
else | |||
{ | |||
encoding = currentCharacterSetECI.EncodingName; | |||
} | |||
try | |||
{ | |||
result.Append(Encoding.GetEncoding(encoding).GetString(readBytes, 0, readBytes.Length)); | |||
} | |||
#if (WINDOWS_PHONE70 || WINDOWS_PHONE71 || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || MONOANDROID || MONOTOUCH) | |||
catch (ArgumentException) | |||
{ | |||
try | |||
{ | |||
// Silverlight only supports a limited number of character sets, trying fallback to UTF-8 | |||
result.Append(Encoding.GetEncoding("UTF-8").GetString(readBytes, 0, readBytes.Length)); | |||
} | |||
catch (Exception) | |||
{ | |||
return false; | |||
} | |||
} | |||
#endif | |||
#if WindowsCE | |||
catch (PlatformNotSupportedException) | |||
{ | |||
try | |||
{ | |||
// WindowsCE doesn't support all encodings. But it is device depended. | |||
// So we try here the some different ones | |||
if (encoding == "ISO-8859-1") | |||
{ | |||
result.Append(Encoding.GetEncoding(1252).GetString(readBytes, 0, readBytes.Length)); | |||
} | |||
else | |||
{ | |||
result.Append(Encoding.GetEncoding("UTF-8").GetString(readBytes, 0, readBytes.Length)); | |||
} | |||
} | |||
catch (Exception) | |||
{ | |||
return false; | |||
} | |||
} | |||
#endif | |||
catch (Exception) | |||
{ | |||
return false; | |||
} | |||
byteSegments.Add(readBytes); | |||
return true; | |||
} | |||
private static char toAlphaNumericChar(int value) | |||
{ | |||
@@ -7,6 +7,7 @@ using System.Diagnostics; | |||
using System.Drawing; | |||
using System.Text; | |||
using System.Windows.Forms; | |||
using ZXing; | |||
namespace Shadowsocks.View | |||
{ | |||
@@ -143,6 +144,7 @@ namespace Shadowsocks.View | |||
CreateMenuItem("Update PAC from GFWList", new EventHandler(this.UpdatePACFromGFWListItem_Click)), | |||
new MenuItem("-"), | |||
CreateMenuItem("Show QRCode...", new EventHandler(this.QRCodeItem_Click)), | |||
CreateMenuItem("Scan QRCode...", new EventHandler(this.ScanQRCodeItem_Click)), | |||
CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)), | |||
CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)), | |||
new MenuItem("-"), | |||
@@ -359,41 +361,32 @@ namespace Shadowsocks.View | |||
private void ScanQRCodeItem_Click(object sender, EventArgs e) | |||
{ | |||
/* | |||
using (Bitmap image = new Bitmap(Screen.PrimaryScreen.Bounds.Width, | |||
using (Bitmap image = new Bitmap(Screen.PrimaryScreen.Bounds.Width, | |||
Screen.PrimaryScreen.Bounds.Height)) | |||
{ | |||
using (Graphics g = Graphics.FromImage(bmpScreenCapture)) | |||
using (Graphics g = Graphics.FromImage(image)) | |||
{ | |||
g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, | |||
Screen.PrimaryScreen.Bounds.Y, | |||
0, 0, | |||
bmpScreenCapture.Size, | |||
image.Size, | |||
CopyPixelOperation.SourceCopy); | |||
} | |||
resultPoints.Clear(); | |||
/* var reader = new BarcodeReader | |||
var reader = new BarcodeReader | |||
{ | |||
TryHarder = true, | |||
PossibleFormats = new List<BarcodeFormat> | |||
{ | |||
{ | |||
BarcodeFormat.QR_CODE | |||
} | |||
} | |||
}; | |||
var result = reader.Decode(image); | |||
var result = barcodeReader.Decode(image); | |||
var timerStart = DateTime.Now.Ticks; | |||
var timerStop = DateTime.Now.Ticks; | |||
if (result == null) | |||
if (result != null) | |||
{ | |||
txtDecoderContent.Text = "No barcode recognized"; | |||
Console.WriteLine(result.Text); | |||
} | |||
labDuration.Text = new TimeSpan(timerStop - timerStart).Milliseconds.ToString("0 ms"); | |||
} | |||
} | |||
* */ | |||
} | |||
private void AutoStartupItem_Click(object sender, EventArgs e) { | |||
@@ -71,6 +71,8 @@ | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="3rd\zxing\BarcodeFormat.cs" /> | |||
<Compile Include="3rd\zxing\BarcodeReader.cs" /> | |||
<Compile Include="3rd\zxing\BarcodeReaderGeneric.cs" /> | |||
<Compile Include="3rd\zxing\BaseLuminanceSource.cs" /> | |||
<Compile Include="3rd\zxing\Binarizer.cs" /> | |||
<Compile Include="3rd\zxing\BinaryBitmap.cs" /> | |||
@@ -78,22 +80,33 @@ | |||
<Compile Include="3rd\zxing\common\BitArray.cs" /> | |||
<Compile Include="3rd\zxing\common\BitMatrix.cs" /> | |||
<Compile Include="3rd\zxing\common\BitSource.cs" /> | |||
<Compile Include="3rd\zxing\common\CharacterSetECI.cs" /> | |||
<Compile Include="3rd\zxing\common\DecoderResult.cs" /> | |||
<Compile Include="3rd\zxing\common\DecodingOptions.cs" /> | |||
<Compile Include="3rd\zxing\common\DefaultGridSampler.cs" /> | |||
<Compile Include="3rd\zxing\common\DetectorResult.cs" /> | |||
<Compile Include="3rd\zxing\common\detector\MathUtils.cs" /> | |||
<Compile Include="3rd\zxing\common\detector\MonochromeRectangleDetector.cs" /> | |||
<Compile Include="3rd\zxing\common\detector\WhiteRectangleDetector.cs" /> | |||
<Compile Include="3rd\zxing\common\ECI.cs" /> | |||
<Compile Include="3rd\zxing\common\EncodingOptions.cs" /> | |||
<Compile Include="3rd\zxing\common\GlobalHistogramBinarizer.cs" /> | |||
<Compile Include="3rd\zxing\common\GridSampler.cs" /> | |||
<Compile Include="3rd\zxing\common\HybridBinarizer.cs" /> | |||
<Compile Include="3rd\zxing\common\PerspectiveTransform.cs" /> | |||
<Compile Include="3rd\zxing\common\reedsolomon\GenericGF.cs" /> | |||
<Compile Include="3rd\zxing\common\reedsolomon\GenericGFPoly.cs" /> | |||
<Compile Include="3rd\zxing\common\reedsolomon\ReedSolomonDecoder.cs" /> | |||
<Compile Include="3rd\zxing\common\reedsolomon\ReedSolomonEncoder.cs" /> | |||
<Compile Include="3rd\zxing\common\StringUtils.cs" /> | |||
<Compile Include="3rd\zxing\DecodeHintType.cs" /> | |||
<Compile Include="3rd\zxing\EncodeHintType.cs" /> | |||
<Compile Include="3rd\zxing\IBarcodeReader.cs" /> | |||
<Compile Include="3rd\zxing\IBarcodeReaderGeneric.cs" /> | |||
<Compile Include="3rd\zxing\LuminanceSource.cs" /> | |||
<Compile Include="3rd\zxing\net2.0\Action.cs" /> | |||
<Compile Include="3rd\zxing\net2.0\Func.cs" /> | |||
<Compile Include="3rd\zxing\net2.0\TimeZoneInfo.cs" /> | |||
<Compile Include="3rd\zxing\qrcode\decoder\BitMatrixParser.cs" /> | |||
<Compile Include="3rd\zxing\qrcode\decoder\DataBlock.cs" /> | |||
<Compile Include="3rd\zxing\qrcode\decoder\DataMask.cs" /> | |||
@@ -125,6 +138,7 @@ | |||
<Compile Include="3rd\zxing\ResultMetadataType.cs" /> | |||
<Compile Include="3rd\zxing\ResultPoint.cs" /> | |||
<Compile Include="3rd\zxing\ResultPointCallback.cs" /> | |||
<Compile Include="3rd\zxing\RGBLuminanceSource.cs" /> | |||
<Compile Include="3rd\zxing\WriterException.cs" /> | |||
<Compile Include="Controller\AutoStartup.cs" /> | |||
<Compile Include="Controller\FileManager.cs" /> | |||