diff --git a/AIStudio.Wpf.ADiagram/AIStudio.Wpf.ADiagram.csproj b/AIStudio.Wpf.ADiagram/AIStudio.Wpf.ADiagram.csproj index 082b033..742acc4 100644 --- a/AIStudio.Wpf.ADiagram/AIStudio.Wpf.ADiagram.csproj +++ b/AIStudio.Wpf.ADiagram/AIStudio.Wpf.ADiagram.csproj @@ -2,7 +2,7 @@ WinExe - net472 + netcoreapp3.1 true @@ -121,20 +121,26 @@ + + + - + + - - - - + + + + + zxing.core.dll + diff --git a/AIStudio.Wpf.ADiagram/ViewModels/MainWindowViewModel.cs b/AIStudio.Wpf.ADiagram/ViewModels/MainWindowViewModel.cs index 8e3b107..59f7cc6 100644 --- a/AIStudio.Wpf.ADiagram/ViewModels/MainWindowViewModel.cs +++ b/AIStudio.Wpf.ADiagram/ViewModels/MainWindowViewModel.cs @@ -1154,18 +1154,18 @@ namespace AIStudio.Wpf.ADiagram.ViewModels List result = new List(); for (var i = 0; i < count; i++) { - var colors = ColorGallery.GetGradient(ColorGallery.StandardThemeColors[i], 10); - for (var j = 9; j >= 0; j--) - { - result.Add(colors[j]); - } + //var colors = ColorGallery.GetGradient(ColorGallery.StandardThemeColors[i], 10); + //for (var j = 9; j >= 0; j--) + //{ + // result.Add(colors[j]); + //} } { - var colors = ColorGallery.GetGradient(Colors.Black, 10); - for (var j = 9; j >= 0; j--) - { - result.Add(colors[j]); - } + //var colors = ColorGallery.GetGradient(Colors.Black, 10); + //for (var j = 9; j >= 0; j--) + //{ + // result.Add(colors[j]); + //} } return result.ToArray(); } diff --git a/AIStudio.Wpf.ADiagram/zxing.core.dll b/AIStudio.Wpf.ADiagram/zxing.core.dll new file mode 100644 index 0000000..1f3303c Binary files /dev/null and b/AIStudio.Wpf.ADiagram/zxing.core.dll differ diff --git a/AIStudio.Wpf.Diagram.sln b/AIStudio.Wpf.Diagram.sln index 7c81cc9..da0164a 100644 --- a/AIStudio.Wpf.Diagram.sln +++ b/AIStudio.Wpf.Diagram.sln @@ -5,34 +5,8 @@ VisualStudioVersion = 16.0.29509.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Util.DiagramDesigner", "Util.DiagramDesigner\Util.DiagramDesigner.csproj", "{3FC9F09D-83EA-4914-8980-A6B4C3352836}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fluent.Ribbon", "Fluent.Ribbon\Fluent.Ribbon\Fluent.Ribbon.csproj", "{8828180F-6840-4019-B151-336FD4CF89B0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfAnimatedGif", "WpfAnimatedGif\WpfAnimatedGif.csproj", "{95DFC433-5097-4F8C-881C-FC0ED172F14E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AIStudio.Wpf.ADiagram", "AIStudio.Wpf.ADiagram\AIStudio.Wpf.ADiagram.csproj", "{9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fluent.Ribbon.Showcase", "Fluent.Ribbon\Fluent.Ribbon.Showcase\Fluent.Ribbon.Showcase.csproj", "{201885CE-BEEC-465E-B0CB-D416494DF611}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dragablz", "Dragablz\Dragablz\Dragablz.csproj", "{62608851-A3A1-467C-8FC2-4EA833BA94F7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Fluent", "Fluent", "{3DCF79F7-3E2E-4104-B294-93FD574C985B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dragablz", "Dragablz", "{3F017B57-F43A-46AC-9265-D0619CEDF935}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DragablzDemo", "Dragablz\DragablzDemo\DragablzDemo.csproj", "{CD59A633-9EFD-4B96-95DE-A3DD7E828BED}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "zxing.core", "zxing.core", "{548B8B1E-71F1-439C-895D-9FA652FBEFFD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zxing.core", "zxing.core\zxing.core\zxing.core.csproj", "{112E5A66-F6AF-407B-B23E-EBD24C0084AB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPFDemo", "zxing.core\WPFDemo\WPFDemo.csproj", "{DA299EFC-BC08-4FD7-8FA0-818057D6EF8E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DragDrop", "DragDrop", "{734F752D-AADA-420D-966C-B2A1EDF220D4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GongSolutions.WPF.DragDrop", "gong-wpf-dragdrop\src\GongSolutions.WPF.DragDrop\GongSolutions.WPF.DragDrop.csproj", "{6B3EBB67-48DD-48DF-80F0-ED530D4724E2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Showcase.WPF.DragDrop", "gong-wpf-dragdrop\src\Showcase\Showcase.WPF.DragDrop.csproj", "{963E3D97-D75A-4096-81D3-1F28DB758254}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -43,60 +17,14 @@ Global {3FC9F09D-83EA-4914-8980-A6B4C3352836}.Debug|Any CPU.Build.0 = Debug|Any CPU {3FC9F09D-83EA-4914-8980-A6B4C3352836}.Release|Any CPU.ActiveCfg = Release|Any CPU {3FC9F09D-83EA-4914-8980-A6B4C3352836}.Release|Any CPU.Build.0 = Release|Any CPU - {8828180F-6840-4019-B151-336FD4CF89B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8828180F-6840-4019-B151-336FD4CF89B0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8828180F-6840-4019-B151-336FD4CF89B0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8828180F-6840-4019-B151-336FD4CF89B0}.Release|Any CPU.Build.0 = Release|Any CPU - {95DFC433-5097-4F8C-881C-FC0ED172F14E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {95DFC433-5097-4F8C-881C-FC0ED172F14E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {95DFC433-5097-4F8C-881C-FC0ED172F14E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {95DFC433-5097-4F8C-881C-FC0ED172F14E}.Release|Any CPU.Build.0 = Release|Any CPU {9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Debug|Any CPU.Build.0 = Debug|Any CPU {9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Release|Any CPU.ActiveCfg = Release|Any CPU {9D2DCA7D-9E0C-4E6E-ACD9-2CD18C75FE34}.Release|Any CPU.Build.0 = Release|Any CPU - {201885CE-BEEC-465E-B0CB-D416494DF611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {201885CE-BEEC-465E-B0CB-D416494DF611}.Debug|Any CPU.Build.0 = Debug|Any CPU - {201885CE-BEEC-465E-B0CB-D416494DF611}.Release|Any CPU.ActiveCfg = Release|Any CPU - {201885CE-BEEC-465E-B0CB-D416494DF611}.Release|Any CPU.Build.0 = Release|Any CPU - {62608851-A3A1-467C-8FC2-4EA833BA94F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {62608851-A3A1-467C-8FC2-4EA833BA94F7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {62608851-A3A1-467C-8FC2-4EA833BA94F7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {62608851-A3A1-467C-8FC2-4EA833BA94F7}.Release|Any CPU.Build.0 = Release|Any CPU - {CD59A633-9EFD-4B96-95DE-A3DD7E828BED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CD59A633-9EFD-4B96-95DE-A3DD7E828BED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CD59A633-9EFD-4B96-95DE-A3DD7E828BED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CD59A633-9EFD-4B96-95DE-A3DD7E828BED}.Release|Any CPU.Build.0 = Release|Any CPU - {112E5A66-F6AF-407B-B23E-EBD24C0084AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {112E5A66-F6AF-407B-B23E-EBD24C0084AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {112E5A66-F6AF-407B-B23E-EBD24C0084AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {112E5A66-F6AF-407B-B23E-EBD24C0084AB}.Release|Any CPU.Build.0 = Release|Any CPU - {DA299EFC-BC08-4FD7-8FA0-818057D6EF8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA299EFC-BC08-4FD7-8FA0-818057D6EF8E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA299EFC-BC08-4FD7-8FA0-818057D6EF8E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA299EFC-BC08-4FD7-8FA0-818057D6EF8E}.Release|Any CPU.Build.0 = Release|Any CPU - {6B3EBB67-48DD-48DF-80F0-ED530D4724E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B3EBB67-48DD-48DF-80F0-ED530D4724E2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B3EBB67-48DD-48DF-80F0-ED530D4724E2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B3EBB67-48DD-48DF-80F0-ED530D4724E2}.Release|Any CPU.Build.0 = Release|Any CPU - {963E3D97-D75A-4096-81D3-1F28DB758254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {963E3D97-D75A-4096-81D3-1F28DB758254}.Debug|Any CPU.Build.0 = Debug|Any CPU - {963E3D97-D75A-4096-81D3-1F28DB758254}.Release|Any CPU.ActiveCfg = Release|Any CPU - {963E3D97-D75A-4096-81D3-1F28DB758254}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {8828180F-6840-4019-B151-336FD4CF89B0} = {3DCF79F7-3E2E-4104-B294-93FD574C985B} - {201885CE-BEEC-465E-B0CB-D416494DF611} = {3DCF79F7-3E2E-4104-B294-93FD574C985B} - {62608851-A3A1-467C-8FC2-4EA833BA94F7} = {3F017B57-F43A-46AC-9265-D0619CEDF935} - {CD59A633-9EFD-4B96-95DE-A3DD7E828BED} = {3F017B57-F43A-46AC-9265-D0619CEDF935} - {112E5A66-F6AF-407B-B23E-EBD24C0084AB} = {548B8B1E-71F1-439C-895D-9FA652FBEFFD} - {DA299EFC-BC08-4FD7-8FA0-818057D6EF8E} = {548B8B1E-71F1-439C-895D-9FA652FBEFFD} - {6B3EBB67-48DD-48DF-80F0-ED530D4724E2} = {734F752D-AADA-420D-966C-B2A1EDF220D4} - {963E3D97-D75A-4096-81D3-1F28DB758254} = {734F752D-AADA-420D-966C-B2A1EDF220D4} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D30FC641-F06C-4E35-AEA5-48A9B6E59CE0} EndGlobalSection diff --git a/Util.DiagramDesigner/Util.DiagramDesigner.csproj b/Util.DiagramDesigner/Util.DiagramDesigner.csproj index 0de8e10..ecda8ae 100644 --- a/Util.DiagramDesigner/Util.DiagramDesigner.csproj +++ b/Util.DiagramDesigner/Util.DiagramDesigner.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1;net462;net472 + netcoreapp3.1 true @@ -14,10 +14,7 @@ - - - - + diff --git a/zxing.core/xx/BarcodeFormat.cs b/zxing.core/xx/BarcodeFormat.cs deleted file mode 100644 index c71fb91..0000000 --- a/zxing.core/xx/BarcodeFormat.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing -{ - /// - /// Enumerates barcode formats known to this package. - /// - /// Sean Owen - [System.Flags] - public enum BarcodeFormat - { - /// Aztec 2D barcode format. - AZTEC = 1, - - /// CODABAR 1D format. - CODABAR = 2, - - /// Code 39 1D format. - CODE_39 = 4, - - /// Code 93 1D format. - CODE_93 = 8, - - /// Code 128 1D format. - CODE_128 = 16, - - /// Data Matrix 2D barcode format. - DATA_MATRIX = 32, - - /// EAN-8 1D format. - EAN_8 = 64, - - /// EAN-13 1D format. - EAN_13 = 128, - - /// ITF (Interleaved Two of Five) 1D format. - ITF = 256, - - /// MaxiCode 2D barcode format. - MAXICODE = 512, - - /// PDF417 format. - PDF_417 = 1024, - - /// QR Code 2D barcode format. - QR_CODE = 2048, - - /// RSS 14 - RSS_14 = 4096, - - /// RSS EXPANDED - RSS_EXPANDED = 8192, - - /// UPC-A 1D format. - UPC_A = 16384, - - /// UPC-E 1D format. - UPC_E = 32768, - - /// UPC/EAN extension format. Not a stand-alone format. - UPC_EAN_EXTENSION = 65536, - - /// MSI - MSI = 131072, - - /// Plessey - PLESSEY = 262144, - - /// Intelligent Mail barcode - IMB = 524288, - - /// - /// UPC_A | UPC_E | EAN_13 | EAN_8 | CODABAR | CODE_39 | CODE_93 | CODE_128 | ITF | RSS_14 | RSS_EXPANDED - /// without MSI (to many false-positives) and IMB (not enough tested, and it looks more like a 2D) - /// - All_1D = UPC_A | UPC_E | EAN_13 | EAN_8 | CODABAR | CODE_39 | CODE_93 | CODE_128 | ITF | RSS_14 | RSS_EXPANDED - } -} \ No newline at end of file diff --git a/zxing.core/xx/BarcodeReader.Bitmap.cs b/zxing.core/xx/BarcodeReader.Bitmap.cs deleted file mode 100644 index 64eedd2..0000000 --- a/zxing.core/xx/BarcodeReader.Bitmap.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.Drawing; - -namespace ZXing -{ - /// - /// A smart class to decode the barcode inside a bitmap object - /// - public class BarcodeReader : BarcodeReader, IBarcodeReader - { - private static readonly Func defaultCreateLuminanceSource = - (bitmap) => new BitmapLuminanceSource(bitmap); - - /// - /// Initializes a new instance of the class. - /// - public BarcodeReader() - : this(null, defaultCreateLuminanceSource, null) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, an exception is thrown when Decode is called - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - public BarcodeReader(Reader reader, - Func createLuminanceSource, - Func createBinarizer - ) - : base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, an exception is thrown when Decode is called - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - /// Sets the function to create a luminance source object for a rgb raw byte array. - public BarcodeReader(Reader reader, - Func createLuminanceSource, - Func createBinarizer, - Func createRGBLuminanceSource - ) - : base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer, createRGBLuminanceSource) - { - } - } -} diff --git a/zxing.core/xx/BarcodeReaderCustom.cs b/zxing.core/xx/BarcodeReaderCustom.cs deleted file mode 100644 index 2a15374..0000000 --- a/zxing.core/xx/BarcodeReaderCustom.cs +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 -{ - /// - /// A smart class to decode the barcode inside a bitmap object - /// - public class BarcodeReader : BarcodeReaderGeneric, IBarcodeReader - { - private readonly Func createLuminanceSource; - - /// - /// Initializes a new instance of the class. - /// - public BarcodeReader(Func createLuminanceSource) - : this(null, createLuminanceSource, null) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, an exception is thrown when Decode is called - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - public BarcodeReader(Reader reader, - Func createLuminanceSource, - Func createBinarizer - ) - : this(reader, createLuminanceSource, createBinarizer, null) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, an exception is thrown when Decode is called - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - /// Sets the function to create a luminance source object for a rgb raw byte array. - public BarcodeReader(Reader reader, - Func createLuminanceSource, - Func createBinarizer, - Func createRGBLuminanceSource - ) - : base(reader, createBinarizer, createRGBLuminanceSource) - { - this.createLuminanceSource = createLuminanceSource; - } - - /// - /// Constructor for additional image formats for one BarcodeReader class - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - /// Sets the function to create a luminance source object for a rgb raw byte array. - protected BarcodeReader(Reader reader, - Func createBinarizer, - Func createRGBLuminanceSource - ) - : base(reader, createBinarizer, createRGBLuminanceSource) - { - } - - /// - /// Optional: Gets or sets the function to create a luminance source object for a bitmap. - /// If null a platform specific default LuminanceSource is used - /// - /// - /// The function to create a luminance source object. - /// - protected Func CreateLuminanceSource - { - get - { - return createLuminanceSource; - } - } - - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - public Result Decode(T barcodeBitmap) - { - if (CreateLuminanceSource == null) - { - throw new InvalidOperationException("You have to declare a luminance source delegate."); - } - - if (barcodeBitmap == null) - throw new ArgumentNullException("barcodeBitmap"); - - var luminanceSource = CreateLuminanceSource(barcodeBitmap); - - return Decode(luminanceSource); - } - - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - public Result[] DecodeMultiple(T barcodeBitmap) - { - if (CreateLuminanceSource == null) - { - throw new InvalidOperationException("You have to declare a luminance source delegate."); - } - - if (barcodeBitmap == null) - throw new ArgumentNullException("barcodeBitmap"); - - var luminanceSource = CreateLuminanceSource(barcodeBitmap); - - return DecodeMultiple(luminanceSource); - } - } -} diff --git a/zxing.core/xx/BarcodeReaderGeneric.cs b/zxing.core/xx/BarcodeReaderGeneric.cs deleted file mode 100644 index a84bcd0..0000000 --- a/zxing.core/xx/BarcodeReaderGeneric.cs +++ /dev/null @@ -1,604 +0,0 @@ -/* - * 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.Multi; -using ZXing.Multi.QrCode; - -namespace ZXing -{ - /// - /// A smart class to decode the barcode inside a bitmap object - /// - public class BarcodeReaderGeneric : IBarcodeReaderGeneric, IMultipleBarcodeReaderGeneric - { - private static readonly Func defaultCreateBinarizer = - (luminanceSource) => new HybridBinarizer(luminanceSource); - - protected static readonly Func defaultCreateRGBLuminanceSource = - (rawBytes, width, height, format) => new RGBLuminanceSource(rawBytes, width, height, format); - - private Reader reader; - private readonly Func createRGBLuminanceSource; -#if !UNITY - private readonly Func createLuminanceSource; -#else - private readonly Func createLuminanceSource; -#endif - private readonly Func createBinarizer; - private bool usePreviousState; - private DecodingOptions options; - - /// - /// Gets or sets the options. - /// - /// - /// The options. - /// - public DecodingOptions Options - { - get { return options ?? (options = new DecodingOptions()); } - set { options = value; } - } - - /// - /// Gets the reader which should be used to find and decode the barcode. - /// - /// - /// The reader. - /// - protected Reader Reader - { - get - { - return reader ?? (reader = new MultiFormatReader()); - } - } - - /// - /// Gets or sets a method which is called if an important point is found - /// - /// - /// The result point callback. - /// - public event Action 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 explicitResultPointFound; - - /// - /// event is executed if a result was found via decode - /// - public event Action ResultFound; - - /// - /// Gets or sets a flag which cause a deeper look into the bitmap - /// - /// - /// true if [try harder]; otherwise, false. - /// - [Obsolete("Please use the Options.TryHarder property instead.")] - public bool TryHarder - { - get { return Options.TryHarder; } - set { Options.TryHarder = value; } - } - - /// - /// Image is a pure monochrome image of a barcode. - /// - /// - /// true if monochrome image of a barcode; otherwise, false. - /// - [Obsolete("Please use the Options.PureBarcode property instead.")] - public bool PureBarcode - { - get { return Options.PureBarcode; } - set { Options.PureBarcode = value; } - } - - /// - /// Specifies what character encoding to use when decoding, where applicable (type String) - /// - /// - /// The character set. - /// - [Obsolete("Please use the Options.CharacterSet property instead.")] - public string CharacterSet - { - get { return Options.CharacterSet; } - set { Options.CharacterSet = value; } - } - - /// - /// Image is known to be of one of a few possible formats. - /// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. - /// - /// - /// The possible formats. - /// - [Obsolete("Please use the Options.PossibleFormats property instead.")] - public IList PossibleFormats - { - get { return Options.PossibleFormats; } - set { Options.PossibleFormats = value; } - } - - /// - /// Gets or sets a value indicating whether the image should be automatically rotated. - /// Rotation is supported for 90, 180 and 270 degrees - /// - /// - /// true if image should be rotated; otherwise, false. - /// - public bool AutoRotate { get; set; } - - /// - /// 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 - /// - /// - /// true if image should be inverted; otherwise, false. - /// - public bool TryInverted { get; set; } - -#if !UNITY - /// - /// Optional: Gets or sets the function to create a luminance source object for a bitmap. - /// If null a platform specific default LuminanceSource is used - /// - /// - /// The function to create a luminance source object. - /// - protected Func CreateLuminanceSource -#else - /// - /// Optional: Gets or sets the function to create a luminance source object for a bitmap. - /// If null a platform specific default LuminanceSource is used - /// - /// - /// The function to create a luminance source object. - /// - protected Func CreateLuminanceSource -#endif - { - get - { - return createLuminanceSource; - } - } - - /// - /// Optional: Gets or sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - /// - /// - /// The function to create a binarizer object. - /// - protected Func CreateBinarizer - { - get - { - return createBinarizer ?? defaultCreateBinarizer; - } - } - - /// - /// Initializes a new instance of the class. - /// - public BarcodeReaderGeneric() - : this(new MultiFormatReader(), null, defaultCreateBinarizer) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, an exception is thrown when Decode is called - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - public BarcodeReaderGeneric(Reader reader, -#if !UNITY - Func createLuminanceSource, -#else - Func createLuminanceSource, -#endif - Func createBinarizer - ) - : this(reader, createLuminanceSource, createBinarizer, null) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, an exception is thrown when Decode is called - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - /// 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. - public BarcodeReaderGeneric(Reader reader, -#if !UNITY - Func createLuminanceSource, -#else - Func createLuminanceSource, -#endif - Func createBinarizer, - Func createRGBLuminanceSource - ) - { - this.reader = reader ?? new MultiFormatReader(); - this.createLuminanceSource = createLuminanceSource; - this.createBinarizer = createBinarizer ?? defaultCreateBinarizer; - this.createRGBLuminanceSource = createRGBLuminanceSource ?? defaultCreateRGBLuminanceSource; - Options.ValueChanged += (o, args) => usePreviousState = false; - usePreviousState = false; - } - -#if !PORTABLE -#if !UNITY - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - public Result Decode(T barcodeBitmap) -#else - /// - /// Decodes the specified barcode bitmap. - /// - /// raw bytes of the image in RGB order - /// - /// - /// - /// the result data or null - /// - 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 - - /// - /// 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. - /// - /// The luminance source. - /// - virtual public Result Decode(LuminanceSource luminanceSource) - { - var result = default(Result); - var binarizer = CreateBinarizer(luminanceSource); - var binaryBitmap = new BinaryBitmap(binarizer); - var multiformatReader = Reader as MultiFormatReader; - 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++) - { - if (usePreviousState && multiformatReader != null) - { - result = multiformatReader.decodeWithState(binaryBitmap); - } - else - { - result = Reader.decode(binaryBitmap, Options.Hints); - usePreviousState = true; - } - - if (result == null) - { - if (TryInverted && luminanceSource.InversionSupported) - { - binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.invert())); - if (usePreviousState && multiformatReader != null) - { - result = multiformatReader.decodeWithState(binaryBitmap); - } - else - { - 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; - } - -#if !PORTABLE -#if !UNITY - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - public Result[] DecodeMultiple(T barcodeBitmap) -#else - /// - /// Decodes the specified barcode bitmap. - /// - /// raw bytes of the image in RGB order - /// - /// - /// - /// the result data or null - /// - public Result[] DecodeMultiple(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 DecodeMultiple(luminanceSource); - } -#endif - - /// - /// Tries to decode barcodes 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. - /// - /// The luminance source. - /// - virtual public Result[] DecodeMultiple(LuminanceSource luminanceSource) - { - var results = default(Result[]); - var binarizer = CreateBinarizer(luminanceSource); - var binaryBitmap = new BinaryBitmap(binarizer); - var rotationCount = 0; - var rotationMaxCount = 1; - MultipleBarcodeReader multiReader = null; - - if (AutoRotate) - { - Options.Hints[DecodeHintType.TRY_HARDER_WITHOUT_ROTATION] = true; - rotationMaxCount = 4; - } - - var formats = Options.PossibleFormats; - if (formats != null && - formats.Count == 1 && - formats.Contains(BarcodeFormat.QR_CODE)) - { - multiReader = new QRCodeMultiReader(); - } - else - { - multiReader = new GenericMultipleBarcodeReader(Reader); - } - - for (; rotationCount < rotationMaxCount; rotationCount++) - { - results = multiReader.decodeMultiple(binaryBitmap, Options.Hints); - - if (results == null) - { - if (TryInverted && luminanceSource.InversionSupported) - { - binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.invert())); - results = multiReader.decodeMultiple(binaryBitmap, Options.Hints); - } - } - - if (results != null || - !luminanceSource.RotateSupported || - !AutoRotate) - break; - - binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.rotateCounterClockwise())); - } - - if (results != null) - { - foreach (var result in results) - { - 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; - } - } - - OnResultsFound(results); - } - - return results; - } - - protected void OnResultsFound(IEnumerable 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); - } - } - - /// - /// Decodes the specified barcode bitmap. - /// - /// The image as byte[] array. - /// The width. - /// The height. - /// The format. - /// - /// the result data or null - /// - 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); - } - - /// - /// Decodes the specified barcode bitmap. - /// - /// The image as byte[] array. - /// The width. - /// The height. - /// The format. - /// - /// the result data or null - /// - public Result[] DecodeMultiple(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format) - { - if (rawRGB == null) - throw new ArgumentNullException("rawRGB"); - - var luminanceSource = createRGBLuminanceSource(rawRGB, width, height, format); - - return DecodeMultiple(luminanceSource); - } - } -} diff --git a/zxing.core/xx/BarcodeWriterGeneric.cs b/zxing.core/xx/BarcodeWriterGeneric.cs deleted file mode 100644 index 8272e89..0000000 --- a/zxing.core/xx/BarcodeWriterGeneric.cs +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 ZXing.Common; -using ZXing.Rendering; - -namespace ZXing -{ - /// - /// A base class for specific barcode writers with specific formats of barcode images. - /// - /// The type of the output. - public class BarcodeWriterGeneric : IBarcodeWriterGeneric - { - private EncodingOptions options; - - /// - /// Gets or sets the barcode format. - /// The value is only suitable if the MultiFormatWriter is used. - /// - public BarcodeFormat Format { get; set; } - - /// - /// Gets or sets the options container for the encoding and renderer process. - /// - public EncodingOptions Options - { - get - { - return (options ?? (options = new EncodingOptions { Height = 100, Width = 100 })); - } - set - { - options = value; - } - } - - /// - /// Gets or sets the writer which encodes the content to a BitMatrix. - /// If no value is set the MultiFormatWriter is used. - /// - public Writer Encoder { get; set; } - - /// - /// Gets or sets the renderer which should be used to render the encoded BitMatrix. - /// - public IBarcodeRenderer Renderer { get; set; } - - /// - /// Encodes the specified contents and returns a BitMatrix array. - /// That array has to be rendered manually or with a IBarcodeRenderer. - /// - /// The contents. - /// - public BitMatrix Encode(string contents) - { - var encoder = Encoder ?? new MultiFormatWriter(); - var currentOptions = Options; - return encoder.encode(contents, Format, currentOptions.Width, currentOptions.Height, currentOptions.Hints); - } - - /// - /// Encodes the specified contents and returns a rendered instance of the barcode. - /// For rendering the instance of the property Renderer is used and has to be set before - /// calling that method. - /// - /// The contents. - /// - public TOutput Write(string contents) - { - if (Renderer == null) - { - throw new InvalidOperationException("You have to set a renderer instance."); - } - - var matrix = Encode(contents); - - return Renderer.Render(matrix, Format, contents, Options); - } - - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// For rendering the instance of the property Renderer is used and has to be set before - /// calling that method. - /// - /// The matrix. - /// - public TOutput Write(BitMatrix matrix) - { - if (Renderer == null) - { - throw new InvalidOperationException("You have to set a renderer instance."); - } - - return Renderer.Render(matrix, Format, null, Options); - } - } -} diff --git a/zxing.core/xx/BaseLuminanceSource.cs b/zxing.core/xx/BaseLuminanceSource.cs deleted file mode 100644 index d22ff5c..0000000 --- a/zxing.core/xx/BaseLuminanceSource.cs +++ /dev/null @@ -1,213 +0,0 @@ -/* -* 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 -{ - /// - /// The base class for luminance sources which supports - /// cropping and rotating based upon the luminance values. - /// - public abstract class BaseLuminanceSource : LuminanceSource - { - // the following channel weights give nearly the same - // gray scale picture as the java version with BufferedImage.TYPE_BYTE_GRAY - // they are used in sub classes for luminance / gray scale calculation - protected const int RChannelWeight = 19562; - protected const int GChannelWeight = 38550; - protected const int BChannelWeight = 7424; - protected const int ChannelWeight = 16; - - /// - /// - /// - protected byte[] luminances; - - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The height. - protected BaseLuminanceSource(int width, int height) - : base(width, height) - { - luminances = new byte[width * height]; - } - - /// - /// Initializes a new instance of the class. - /// - /// The luminance array. - /// The width. - /// The height. - protected BaseLuminanceSource(byte[] luminanceArray, int width, int height) - : base(width, height) - { - luminances = new byte[width * height]; - Buffer.BlockCopy(luminanceArray, 0, luminances, 0, width * height); - } - - /// - /// Fetches one row of luminance data from the underlying platform's bitmap. Values range from - /// 0 (black) to 255 (white). It is preferable for implementations of this method - /// to only fetch this row rather than the whole image, since no 2D Readers may be installed and - /// getMatrix() may never be called. - /// - /// The row to fetch, 0 <= y < Height. - /// An optional preallocated array. If null or too small, it will be ignored. - /// Always use the returned object, and ignore the .length of the array. - /// - /// An array containing the luminance data. - /// - override public byte[] getRow(int y, byte[] row) - { - int width = Width; - if (row == null || row.Length < width) - { - row = new byte[width]; - } - for (int i = 0; i < width; i++) - row[i] = luminances[y * width + i]; - return row; - } - - public override byte[] Matrix - { - get { return luminances; } - } - - /// - /// Returns a new object with rotated image data by 90 degrees counterclockwise. - /// Only callable if {@link #isRotateSupported()} is true. - /// - /// - /// A rotated version of this object. - /// - public override LuminanceSource rotateCounterClockwise() - { - var rotatedLuminances = new byte[Width * Height]; - var newWidth = Height; - var newHeight = Width; - var localLuminances = Matrix; - for (var yold = 0; yold < Height; yold++) - { - for (var xold = 0; xold < Width; xold++) - { - var ynew = newHeight - xold - 1; - var xnew = yold; - rotatedLuminances[ynew * newWidth + xnew] = localLuminances[yold * Width + xold]; - } - } - return CreateLuminanceSource(rotatedLuminances, newWidth, newHeight); - } - - /// - /// TODO: not implemented yet - /// - /// - /// A rotated version of this object. - /// - public override LuminanceSource rotateCounterClockwise45() - { - // TODO: implement a good 45 degrees rotation without lost of information - return base.rotateCounterClockwise45(); - } - - /// - /// - /// Whether this subclass supports counter-clockwise rotation. - public override bool RotateSupported - { - get - { - return true; - } - } - - /// - /// Returns a new object with cropped image data. Implementations may keep a reference to the - /// original data rather than a copy. Only callable if CropSupported is true. - /// - /// The left coordinate, 0 <= left < Width. - /// The top coordinate, 0 <= top <= Height. - /// The width of the rectangle to crop. - /// The height of the rectangle to crop. - /// - /// A cropped version of this object. - /// - public override LuminanceSource crop(int left, int top, int width, int height) - { - if (left + width > Width || top + height > Height) - { - throw new ArgumentException("Crop rectangle does not fit within image data."); - } - var croppedLuminances = new byte[width * height]; - var oldLuminances = Matrix; - var oldWidth = Width; - var oldRightBound = left + width; - var oldBottomBound = top + height; - for (int yold = top, ynew = 0; yold < oldBottomBound; yold++, ynew++) - { - for (int xold = left, xnew = 0; xold < oldRightBound; xold++, xnew++) - { - croppedLuminances[ynew * width + xnew] = oldLuminances[yold * oldWidth + xold]; - } - } - return CreateLuminanceSource(croppedLuminances, width, height); - } - - /// - /// - /// Whether this subclass supports cropping. - public override bool CropSupported - { - get - { - return true; - } - } - - /// - /// - /// Whether this subclass supports invertion. - public override bool InversionSupported - { - get - { - return true; - } - } - - /// - /// Inverts the luminance values (newValue = 255 - oldValue) - /// - public override LuminanceSource invert() - { - return new InvertedLuminanceSource(this); - } - - /// - /// Should create a new luminance source with the right class type. - /// The method is used in methods crop and rotate. - /// - /// The new luminances. - /// The width. - /// The height. - /// - protected abstract LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height); - } -} diff --git a/zxing.core/xx/Binarizer.cs b/zxing.core/xx/Binarizer.cs deleted file mode 100644 index 9855176..0000000 --- a/zxing.core/xx/Binarizer.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -using ZXing.Common; - -namespace ZXing -{ - /// This class hierarchy provides a set of methods to convert luminance data to 1 bit data. - /// It allows the algorithm to vary polymorphically, for example allowing a very expensive - /// thresholding technique for servers and a fast one for mobile. It also permits the implementation - /// to vary, e.g. a JNI version for Android and a Java fallback version for other platforms. - /// - /// dswitkin@google.com (Daniel Switkin) - /// - public abstract class Binarizer - { - private readonly LuminanceSource source; - - /// - /// Initializes a new instance of the class. - /// - /// The source. - protected internal Binarizer(LuminanceSource source) - { - if (source == null) - { - throw new ArgumentException("Source must be non-null."); - } - this.source = source; - } - - /// - /// Gets the luminance source object. - /// - virtual public LuminanceSource LuminanceSource - { - get - { - return source; - } - } - - /// Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - /// cached data. Callers should assume this method is expensive and call it as seldom as possible. - /// This method is intended for decoding 1D barcodes and may choose to apply sharpening. - /// For callers which only examine one row of pixels at a time, the same BitArray should be reused - /// and passed in with each call for performance. However it is legal to keep more than one row - /// at a time if needed. - /// - /// The row to fetch, which must be in [0, bitmap height) - /// An optional preallocated array. If null or too small, it will be ignored. - /// If used, the Binarizer will call BitArray.clear(). Always use the returned object. - /// - /// The array of bits for this row (true means black). - public abstract BitArray getBlackRow(int y, BitArray row); - - /// Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive - /// and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or - /// may not apply sharpening. Therefore, a row from this matrix may not be identical to one - /// fetched using getBlackRow(), so don't mix and match between them. - /// - /// The 2D array of bits for the image (true means black). - public abstract BitMatrix BlackMatrix { get; } - - /// 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. - /// - /// The LuminanceSource this Binarizer will operate on. - /// A new concrete Binarizer implementation object. - public abstract Binarizer createBinarizer(LuminanceSource source); - - /// - /// Gets the width of the luminance source object. - /// - public int Width - { - get { return source.Width; } - } - - /// - /// Gets the height of the luminance source object. - /// - public int Height - { - get { return source.Height; } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/BinaryBitmap.cs b/zxing.core/xx/BinaryBitmap.cs deleted file mode 100644 index 280329e..0000000 --- a/zxing.core/xx/BinaryBitmap.cs +++ /dev/null @@ -1,180 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using ZXing.Common; - -namespace ZXing -{ - /// - /// This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects - /// accept a BinaryBitmap and attempt to decode it. - /// - /// dswitkin@google.com (Daniel Switkin) - public sealed class BinaryBitmap - { - private readonly Binarizer binarizer; - private BitMatrix matrix; - - public BinaryBitmap(Binarizer binarizer) - { - if (binarizer == null) - { - throw new ArgumentException("Binarizer must be non-null."); - } - this.binarizer = binarizer; - } - - internal BinaryBitmap(BitMatrix matrix) - { - if (matrix == null) - { - throw new ArgumentException("matrix must be non-null."); - } - this.matrix = matrix; - } - - /// - /// The width of the bitmap. - /// - public int Width - { - get - { - return binarizer.Width; - } - - } - /// - /// The height of the bitmap. - /// - public int Height - { - get - { - return binarizer.Height; - } - - } - - /// - /// Converts one row of luminance data to 1 bit data. May actually do the conversion, or return - /// cached data. Callers should assume this method is expensive and call it as seldom as possible. - /// This method is intended for decoding 1D barcodes and may choose to apply sharpening. - /// - /// The row to fetch, which must be in [0, bitmap height). - /// An optional preallocated array. If null or too small, it will be ignored. - /// If used, the Binarizer will call BitArray.clear(). Always use the returned object. - /// - /// The array of bits for this row (true means black). - public BitArray getBlackRow(int y, BitArray row) - { - return binarizer.getBlackRow(y, row); - } - - /// - /// Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive - /// and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or - /// may not apply sharpening. Therefore, a row from this matrix may not be identical to one - /// fetched using getBlackRow(), so don't mix and match between them. - /// - /// The 2D array of bits for the image (true means black). - public BitMatrix BlackMatrix - { - get - { - // The matrix is created on demand the first time it is requested, then cached. There are two - // reasons for this: - // 1. This work will never be done if the caller only installs 1D Reader objects, or if a - // 1D Reader finds a barcode before the 2D Readers run. - // 2. This work will only be done once even if the caller installs multiple 2D Readers. - return matrix ?? (matrix = binarizer.BlackMatrix); - } - } - - /// - /// Whether this bitmap can be cropped. - /// - public bool CropSupported - { - get - { - return binarizer.LuminanceSource.CropSupported; - } - } - - /// - /// Returns a new object with cropped image data. Implementations may keep a reference to the - /// original data rather than a copy. Only callable if isCropSupported() is true. - /// - /// The left coordinate, which must be in [0, Width) - /// The top coordinate, which must be in [0, Height) - /// The width of the rectangle to crop. - /// The height of the rectangle to crop. - /// A cropped version of this object. - public BinaryBitmap crop(int left, int top, int width, int height) - { - var newSource = binarizer.LuminanceSource.crop(left, top, width, height); - return new BinaryBitmap(binarizer.createBinarizer(newSource)); - } - - /// - /// Whether this bitmap supports counter-clockwise rotation. - /// - public bool RotateSupported - { - get - { - return binarizer.LuminanceSource.RotateSupported; - } - - } - - /// - /// Returns a new object with rotated image data by 90 degrees counterclockwise. - /// Only callable if is true. - /// - /// A rotated version of this object. - public BinaryBitmap rotateCounterClockwise() - { - var newSource = binarizer.LuminanceSource.rotateCounterClockwise(); - return new BinaryBitmap(binarizer.createBinarizer(newSource)); - } - - /// - /// Returns a new object with rotated image data by 45 degrees counterclockwise. - /// Only callable if is true. - /// - /// A rotated version of this object. - public BinaryBitmap rotateCounterClockwise45() - { - LuminanceSource newSource = binarizer.LuminanceSource.rotateCounterClockwise45(); - return new BinaryBitmap(binarizer.createBinarizer(newSource)); - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - var blackMatrix = BlackMatrix; - return blackMatrix != null ? blackMatrix.ToString() : String.Empty; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/DecodeHintType.cs b/zxing.core/xx/DecodeHintType.cs deleted file mode 100644 index d5c161e..0000000 --- a/zxing.core/xx/DecodeHintType.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -namespace ZXing -{ - /// - /// Encapsulates a type of hint that a caller may pass to a barcode reader to help it - /// more quickly or accurately decode it. It is up to implementations to decide what, - /// if anything, to do with the information that is supplied. - /// - /// - /// Sean Owen - /// dswitkin@google.com (Daniel Switkin) - public enum DecodeHintType - { - /// - /// Unspecified, application-specific hint. Maps to an unspecified . - /// - OTHER, - - /// - /// Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; - /// use = true. - /// - PURE_BARCODE, - - /// - /// Image is known to be of one of a few possible formats. - /// Maps to a of s. - /// - POSSIBLE_FORMATS, - - /// - /// Spend more time to try to find a barcode; optimize for accuracy, not speed. - /// Doesn't matter what it maps to; use = true. - /// - TRY_HARDER, - - /// - /// Specifies what character encoding to use when decoding, where applicable (type String) - /// - CHARACTER_SET, - - /// - /// Allowed lengths of encoded data -- reject anything else. Maps to an int[]. - /// - ALLOWED_LENGTHS, - - /// - /// Assume Code 39 codes employ a check digit. Maps to . - /// - ASSUME_CODE_39_CHECK_DIGIT, - - /// - /// The caller needs to be notified via callback when a possible - /// is found. Maps to a . - /// - NEED_RESULT_POINT_CALLBACK, - - /// - /// Assume MSI codes employ a check digit. Maps to . - /// - ASSUME_MSI_CHECK_DIGIT, - - /// - /// if Code39 could be detected try to use extended mode for full ASCII character set - /// Maps to . - /// - USE_CODE_39_EXTENDED_MODE, - - /// - /// Don't fail if a Code39 is detected but can't be decoded in extended mode. - /// Return the raw Code39 result instead. Maps to . - /// - RELAXED_CODE_39_EXTENDED_MODE, - - /// - /// 1D readers supporting rotation with TRY_HARDER enabled. - /// But BarcodeReader class can do auto-rotating for 1D and 2D codes. - /// Enabling that option prevents 1D readers doing double rotation. - /// BarcodeReader enables that option automatically if "global" auto-rotation is enabled. - /// Maps to . - /// - TRY_HARDER_WITHOUT_ROTATION, - - /// - /// Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. - /// For example this affects FNC1 handling for Code 128 (aka GS1-128). Doesn't matter what it maps to; - /// use . - /// - ASSUME_GS1, - - /// - /// 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 . - /// - RETURN_CODABAR_START_END, - - /// - /// Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. - /// Maps to an of the allowed extension lengths, for example [2], [5], or [2, 5]. - /// If it is optional to have an extension, do not set this hint. If this is set, - /// and a UPC or EAN barcode is found but an extension is not, then no result will be returned - /// at all. - /// - ALLOWED_EAN_EXTENSIONS - } -} \ No newline at end of file diff --git a/zxing.core/xx/Dimension.cs b/zxing.core/xx/Dimension.cs deleted file mode 100644 index 2577347..0000000 --- a/zxing.core/xx/Dimension.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing -{ - /// - /// Simply encapsulates a width and height. - /// - public sealed class Dimension - { - private readonly int width; - private readonly int height; - - public Dimension(int width, int height) - { - if (width < 0 || height < 0) - { - throw new ArgumentException(); - } - this.width = width; - this.height = height; - } - - public int Width - { - get { return width; } - } - - public int Height - { - get { return height; } - } - - public override bool Equals(Object other) - { - if (other is Dimension) - { - var d = (Dimension)other; - return width == d.width && height == d.height; - } - return false; - } - - public override int GetHashCode() - { - return width * 32713 + height; - } - - public override String ToString() - { - return width + "x" + height; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/EncodeHintType.cs b/zxing.core/xx/EncodeHintType.cs deleted file mode 100644 index f2d546f..0000000 --- a/zxing.core/xx/EncodeHintType.cs +++ /dev/null @@ -1,131 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing -{ - /// - /// These are a set of hints that you may pass to Writers to specify their behavior. - /// - /// dswitkin@google.com (Daniel Switkin) - public enum EncodeHintType - { - /// - /// Specifies the width of the barcode image - /// type: - /// - WIDTH, - - /// - /// Specifies the height of the barcode image - /// type: - /// - HEIGHT, - - /// - /// Don't put the content string into the output image. - /// type: - /// - PURE_BARCODE, - - /// - /// Specifies what degree of error correction to use, for example in QR Codes. - /// Type depends on the encoder. For example for QR codes it's type - /// - /// For Aztec it is of type , representing the minimal percentage of error correction words. - /// Note: an Aztec symbol should have a minimum of 25% EC words. - /// For PDF417 it is of type or (between 0 and 8), - /// - ERROR_CORRECTION, - - /// - /// Specifies what character encoding to use where applicable. - /// type: - /// - CHARACTER_SET, - - /// - /// Specifies margin, in pixels, to use when generating the barcode. The meaning can vary - /// by format; for example it controls margin before and after the barcode horizontally for - /// most 1D formats. - /// type: - /// - MARGIN, - - /// - /// Specifies whether to use compact mode for PDF417. - /// type: - /// - PDF417_COMPACT, - - /// - /// Specifies what compaction mode to use for PDF417. - /// type: - /// - PDF417_COMPACTION, - - /// - /// Specifies the minimum and maximum number of rows and columns for PDF417. - /// type: - /// - PDF417_DIMENSIONS, - - /// - /// Don't append ECI segment. - /// That is against the specification of QR Code but some - /// readers have problems if the charset is switched from - /// ISO-8859-1 (default) to UTF-8 with the necessary ECI segment. - /// If you set the property to true you can use UTF-8 encoding - /// and the ECI segment is omitted. - /// type: - /// - DISABLE_ECI, - - /// - /// Specifies the matrix shape for Data Matrix (type ) - /// - DATA_MATRIX_SHAPE, - - /// - /// Specifies a minimum barcode size (type ). Only applicable to Data Matrix now. - /// - MIN_SIZE, - - /// - /// Specifies a maximum barcode size (type ). Only applicable to Data Matrix now. - /// - MAX_SIZE, - - /// - /// if true, don't switch to codeset C for numbers - /// - CODE128_FORCE_CODESET_B, - - /// - /// Specifies the default encodation for Data Matrix (type ) - /// Make sure that the content fits into the encodation value, otherwise there will be an exception thrown. - /// standard value: Encodation.ASCII - /// - DATA_MATRIX_DEFAULT_ENCODATION, - - /// - /// Specifies the required number of layers for an Aztec code: - /// a negative number (-1, -2, -3, -4) specifies a compact Aztec code - /// 0 indicates to use the minimum number of layers (the default) - /// a positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code - /// - AZTEC_LAYERS, - } -} \ No newline at end of file diff --git a/zxing.core/xx/FormatException.cs b/zxing.core/xx/FormatException.cs deleted file mode 100644 index 6b9452f..0000000 --- a/zxing.core/xx/FormatException.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing -{ - /// - /// Thrown when a barcode was successfully detected, but some aspect of - /// the content did not conform to the barcode's format rules. This could have - /// been due to a mis-detection. - /// Sean Owen - /// - public sealed class FormatException : ReaderException - { - private FormatException() - { - } - - private FormatException(Exception innerException) - : base(innerException) - { - } - - new public static FormatException Instance - { - get { return new FormatException(); } - } - - public static FormatException getInstance(Exception innerExc) - { - return new FormatException(innerExc); - } - } -} diff --git a/zxing.core/xx/IBarcodeReader.cs b/zxing.core/xx/IBarcodeReader.cs deleted file mode 100644 index b734135..0000000 --- a/zxing.core/xx/IBarcodeReader.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 -{ - /// - /// Interface for a smart class to decode the barcode inside a bitmap object - /// - public interface IBarcodeReader - { - /// - /// event is executed when a result point was found - /// - event Action ResultPointFound; - - /// - /// event is executed when a result was found via decode - /// - event Action ResultFound; - - /// - /// Gets or sets a flag which cause a deeper look into the bitmap - /// - /// - /// true if [try harder]; otherwise, false. - /// - [Obsolete("Please use the Options.TryHarder property instead.")] - bool TryHarder { get; set; } - - /// - /// Image is a pure monochrome image of a barcode. - /// - /// - /// true if monochrome image of a barcode; otherwise, false. - /// - [Obsolete("Please use the Options.PureBarcode property instead.")] - bool PureBarcode { get; set; } - - /// - /// Specifies what character encoding to use when decoding, where applicable (type String) - /// - /// - /// The character set. - /// - [Obsolete("Please use the Options.CharacterSet property instead.")] - string CharacterSet { get; set; } - - /// - /// Image is known to be of one of a few possible formats. - /// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. - /// - /// - /// The possible formats. - /// - [Obsolete("Please use the Options.PossibleFormats property instead.")] - IList PossibleFormats { get; set; } - - /// - /// Specifies some options which influence the decoding process - /// - DecodingOptions Options { get; set; } - - /// - /// Decodes the specified barcode bitmap which is given by a generic byte array with the order RGB24. - /// - /// The image as RGB24 array. - /// The width. - /// The height. - /// The format. - /// - /// the result data or null - /// - Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format); - - /// - /// 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. - /// - /// The luminance source. - /// - Result Decode(LuminanceSource luminanceSource); - } -} diff --git a/zxing.core/xx/IBarcodeReaderCustom.cs b/zxing.core/xx/IBarcodeReaderCustom.cs deleted file mode 100644 index 3a9098f..0000000 --- a/zxing.core/xx/IBarcodeReaderCustom.cs +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 -{ - /// - /// Interface for a smart class to decode the barcode inside a bitmap object - /// - public partial interface IBarcodeReader - { - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - Result Decode(T barcodeBitmap); - } -} diff --git a/zxing.core/xx/IBarcodeReaderGeneric.cs b/zxing.core/xx/IBarcodeReaderGeneric.cs deleted file mode 100644 index 32cbc26..0000000 --- a/zxing.core/xx/IBarcodeReaderGeneric.cs +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 -{ - /// - /// Interface for a smart class to decode the barcode inside a bitmap object - /// - /// gives the type of the input data - public interface IBarcodeReaderGeneric - { - /// - /// event is executed when a result point was found - /// - event Action ResultPointFound; - - /// - /// event is executed when a result was found via decode - /// - event Action ResultFound; - - /// - /// Gets or sets a flag which cause a deeper look into the bitmap - /// - /// - /// true if [try harder]; otherwise, false. - /// - [Obsolete("Please use the Options.TryHarder property instead.")] - bool TryHarder { get; set; } - - /// - /// Image is a pure monochrome image of a barcode. - /// - /// - /// true if monochrome image of a barcode; otherwise, false. - /// - [Obsolete("Please use the Options.PureBarcode property instead.")] - bool PureBarcode { get; set; } - - /// - /// Specifies what character encoding to use when decoding, where applicable (type String) - /// - /// - /// The character set. - /// - [Obsolete("Please use the Options.CharacterSet property instead.")] - string CharacterSet { get; set; } - - /// - /// Image is known to be of one of a few possible formats. - /// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. - /// - /// - /// The possible formats. - /// - [Obsolete("Please use the Options.PossibleFormats property instead.")] - IList PossibleFormats { get; set; } - - /// - /// Specifies some options which influence the decoding process - /// - DecodingOptions Options { get; set; } - - /// - /// Decodes the specified barcode bitmap which is given by a generic byte array. - /// - /// The barcode bitmap. - /// The width. - /// The height. - /// The format. - /// - /// the result data or null - /// - Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format); - - /// - /// 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. - /// - /// The luminance source. - /// - Result Decode(LuminanceSource luminanceSource); - -#if !PORTABLE -#if !UNITY - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - Result Decode(T barcodeBitmap); -#else - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - Result Decode(T rawRGB, int width, int height); -#endif -#endif - } -} diff --git a/zxing.core/xx/IBarcodeWriter.cs b/zxing.core/xx/IBarcodeWriter.cs deleted file mode 100644 index c88ed6e..0000000 --- a/zxing.core/xx/IBarcodeWriter.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 ZXing.Common; - -#if MONOTOUCH -#if __UNIFIED__ -using UIKit; -#else -using MonoTouch.UIKit; -#endif -#endif - -namespace ZXing -{ - /// - /// Interface for a smart class to encode some content into a barcode - /// - public interface IBarcodeWriter - { - /// - /// Encodes the specified contents. - /// - /// The contents. - /// - BitMatrix Encode(string contents); - -#if MONOTOUCH - /// - /// Creates a visual representation of the contents - /// - UIImage Write(string contents); - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// - UIImage Write(BitMatrix matrix); -#endif - -#if MONOANDROID - /// - /// Creates a visual representation of the contents - /// - Android.Graphics.Bitmap Write(string contents); - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// - Android.Graphics.Bitmap Write(BitMatrix matrix); -#endif - -#if UNITY - /// - /// Creates a visual representation of the contents - /// - UnityEngine.Color32[] Write(string contents); - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// - UnityEngine.Color32[] Write(BitMatrix matrix); -#endif - -#if SILVERLIGHT - /// - /// Creates a visual representation of the contents - /// - System.Windows.Media.Imaging.WriteableBitmap Write(string contents); - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// - System.Windows.Media.Imaging.WriteableBitmap Write(BitMatrix matrix); -#endif - -#if NETFX_CORE - /// - /// Creates a visual representation of the contents - /// - Windows.UI.Xaml.Media.Imaging.WriteableBitmap Write(string contents); - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// - Windows.UI.Xaml.Media.Imaging.WriteableBitmap Write(BitMatrix matrix); -#endif - -#if (NET40 || NET35 || NET20) && !UNITY - /// - /// Creates a visual representation of the contents - /// - System.Drawing.Bitmap Write(string contents); - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// - System.Drawing.Bitmap Write(BitMatrix matrix); -#endif - } -} diff --git a/zxing.core/xx/IBarcodeWriterGeneric.cs b/zxing.core/xx/IBarcodeWriterGeneric.cs deleted file mode 100644 index 63d0c7e..0000000 --- a/zxing.core/xx/IBarcodeWriterGeneric.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 ZXing.Common; - -namespace ZXing -{ -#if !(WINDOWS_PHONE || WindowsCE) - /// - /// Interface for a smart class to encode some content into a barcode - /// - public interface IBarcodeWriterGeneric -#else - /// - /// Interface for a smart class to encode some content into a barcode - /// - public interface IBarcodeWriterGeneric -#endif - { - /// - /// Encodes the specified contents. - /// - /// The contents. - /// - BitMatrix Encode(string contents); - - /// - /// Creates a visual representation of the contents - /// - /// The contents. - /// - TOutput Write(string contents); - - /// - /// Returns a rendered instance of the barcode which is given by a BitMatrix. - /// - /// The matrix. - /// - TOutput Write(BitMatrix matrix); - } -} diff --git a/zxing.core/xx/IMultipleBarcodeReader.cs b/zxing.core/xx/IMultipleBarcodeReader.cs deleted file mode 100644 index 2157b9b..0000000 --- a/zxing.core/xx/IMultipleBarcodeReader.cs +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 -{ - /// - /// Interface for a smart class to decode multiple barcodes inside a bitmap object - /// - public interface IMultipleBarcodeReader - { - /// - /// event is executed when a result point was found - /// - event Action ResultPointFound; - - /// - /// event is executed when a result was found via decode - /// - event Action ResultFound; - - /// - /// Gets or sets a flag which cause a deeper look into the bitmap - /// - /// - /// true if [try harder]; otherwise, false. - /// - [Obsolete("Please use the Options.TryHarder property instead.")] - bool TryHarder { get; set; } - - /// - /// Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; - /// use {@link Boolean#TRUE}. - /// - /// - /// true if monochrome image of a barcode; otherwise, false. - /// - [Obsolete("Please use the Options.PureBarcode property instead.")] - bool PureBarcode { get; set; } - - /// - /// Specifies what character encoding to use when decoding, where applicable (type String) - /// - /// - /// The character set. - /// - [Obsolete("Please use the Options.CharacterSet property instead.")] - string CharacterSet { get; set; } - - /// - /// Image is known to be of one of a few possible formats. - /// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. - /// - /// - /// The possible formats. - /// - [Obsolete("Please use the Options.PossibleFormats property instead.")] - IList PossibleFormats { get; set; } - - /// - /// Specifies some options which influence the decoding process - /// - DecodingOptions Options { get; set; } - - /// - /// Decodes the specified barcode bitmap which is given by a generic byte array with the order RGB24. - /// - /// The image as RGB24 array. - /// The width. - /// The height. - /// The format. - /// - /// the result data or null - /// - Result[] DecodeMultiple(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format); - - /// - /// Tries to decode barcodes 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. - /// - /// The luminance source. - /// - Result[] DecodeMultiple(LuminanceSource luminanceSource); - } -} diff --git a/zxing.core/xx/IMultipleBarcodeReaderGeneric.cs b/zxing.core/xx/IMultipleBarcodeReaderGeneric.cs deleted file mode 100644 index 7ac1d3f..0000000 --- a/zxing.core/xx/IMultipleBarcodeReaderGeneric.cs +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 -{ - /// - /// Interface for a smart class to decode multiple barcodes inside a bitmap object - /// - public interface IMultipleBarcodeReaderGeneric - { - /// - /// event is executed when a result point was found - /// - event Action ResultPointFound; - - /// - /// event is executed when a result was found via decode - /// - event Action ResultFound; - - /// - /// Gets or sets a flag which cause a deeper look into the bitmap - /// - /// - /// true if [try harder]; otherwise, false. - /// - [Obsolete("Please use the Options.TryHarder property instead.")] - bool TryHarder { get; set; } - - /// - /// Image is a pure monochrome image of a barcode. Doesn't matter what it maps to; - /// use {@link Boolean#TRUE}. - /// - /// - /// true if monochrome image of a barcode; otherwise, false. - /// - [Obsolete("Please use the Options.PureBarcode property instead.")] - bool PureBarcode { get; set; } - - /// - /// Specifies what character encoding to use when decoding, where applicable (type String) - /// - /// - /// The character set. - /// - [Obsolete("Please use the Options.CharacterSet property instead.")] - string CharacterSet { get; set; } - - /// - /// Image is known to be of one of a few possible formats. - /// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. - /// - /// - /// The possible formats. - /// - [Obsolete("Please use the Options.PossibleFormats property instead.")] - IList PossibleFormats { get; set; } - - /// - /// Specifies some options which influence the decoding process - /// - DecodingOptions Options { get; set; } - - /// - /// Decodes the specified barcode bitmap which is given by a generic byte array with the order RGB24. - /// - /// The barcode bitmap. - /// The width. - /// The height. - /// The format. - /// - /// the result data or null - /// - Result[] DecodeMultiple(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format); - - /// - /// Tries to decode barcodes 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. - /// - /// The luminance source. - /// - Result[] DecodeMultiple(LuminanceSource luminanceSource); - -#if !PORTABLE -#if !UNITY - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - Result[] DecodeMultiple(T barcodeBitmap); -#else - /// - /// Decodes the specified barcode bitmap. - /// - /// The barcode bitmap. - /// the result data or null - Result[] DecodeMultiple(T rawRGB, int width, int height); -#endif -#endif - } -} diff --git a/zxing.core/xx/InvertedLuminanceSource.cs b/zxing.core/xx/InvertedLuminanceSource.cs deleted file mode 100644 index bb2a82a..0000000 --- a/zxing.core/xx/InvertedLuminanceSource.cs +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2013 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 -{ - /// - /// A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes - /// white and vice versa, and each value becomes (255-value). - /// - /// Sean Owen - public sealed class InvertedLuminanceSource : LuminanceSource - { - private readonly LuminanceSource @delegate; - private byte[] invertedMatrix; - - /// - /// Initializes a new instance of the class. - /// - /// The @delegate. - public InvertedLuminanceSource(LuminanceSource @delegate) - : base(@delegate.Width, @delegate.Height) - { - this.@delegate = @delegate; - } - - /// - /// Fetches one row of luminance data from the underlying platform's bitmap. Values range from - /// 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have - /// to bitwise and with 0xff for each value. It is preferable for implementations of this method - /// to only fetch this row rather than the whole image, since no 2D Readers may be installed and - /// getMatrix() may never be called. - /// - /// The row to fetch, 0 <= y < Height. - /// An optional preallocated array. If null or too small, it will be ignored. - /// Always use the returned object, and ignore the .length of the array. - /// - /// An array containing the luminance data. - /// - override public byte[] getRow(int y, byte[] row) - { - row = @delegate.getRow(y, row); - int width = Width; - for (int i = 0; i < width; i++) - { - row[i] = (byte)(255 - (row[i] & 0xFF)); - } - return row; - } - - /// - /// Fetches luminance data for the underlying bitmap. Values should be fetched using: - /// int luminance = array[y * width + x] & 0xff; - /// - /// A row-major 2D array of luminance values. Do not use result.length as it may be - /// larger than width * height bytes on some platforms. Do not modify the contents - /// of the result. - /// - override public byte[] Matrix - { - get - { - if (invertedMatrix == null) - { - byte[] matrix = @delegate.Matrix; - int length = Width*Height; - invertedMatrix = new byte[length]; - for (int i = 0; i < length; i++) - { - invertedMatrix[i] = (byte) (255 - (matrix[i] & 0xFF)); - } - } - return invertedMatrix; - } - } - - /// - /// - /// Whether this subclass supports cropping. - override public bool CropSupported - { - get { return @delegate.CropSupported; } - } - - /// - /// Returns a new object with cropped image data. Implementations may keep a reference to the - /// original data rather than a copy. Only callable if CropSupported is true. - /// - /// The left coordinate, 0 <= left < Width. - /// The top coordinate, 0 <= top <= Height. - /// The width of the rectangle to crop. - /// The height of the rectangle to crop. - /// - /// A cropped version of this object. - /// - override public LuminanceSource crop(int left, int top, int width, int height) - { - return new InvertedLuminanceSource(@delegate.crop(left, top, width, height)); - } - - /// - /// - /// Whether this subclass supports counter-clockwise rotation. - override public bool RotateSupported - { - get { return @delegate.RotateSupported; } - } - - /// - /// Inverts this instance. - /// - /// original delegate {@link LuminanceSource} since invert undoes itself - override public LuminanceSource invert() - { - return @delegate; - } - - /// - /// Returns a new object with rotated image data by 90 degrees counterclockwise. - /// Only callable if {@link #isRotateSupported()} is true. - /// - /// - /// A rotated version of this object. - /// - override public LuminanceSource rotateCounterClockwise() - { - return new InvertedLuminanceSource(@delegate.rotateCounterClockwise()); - } - - /// - /// Returns a new object with rotated image data by 45 degrees counterclockwise. - /// Only callable if {@link #isRotateSupported()} is true. - /// - /// - /// A rotated version of this object. - /// - override public LuminanceSource rotateCounterClockwise45() - { - return new InvertedLuminanceSource(@delegate.rotateCounterClockwise45()); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/LuminanceSource.cs b/zxing.core/xx/LuminanceSource.cs deleted file mode 100644 index 01f1602..0000000 --- a/zxing.core/xx/LuminanceSource.cs +++ /dev/null @@ -1,194 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Text; - -namespace ZXing -{ - /// - /// The purpose of this class hierarchy is to abstract different bitmap implementations across - /// platforms into a standard interface for requesting greyscale luminance values. The interface - /// only provides immutable methods; therefore crop and rotation create copies. This is to ensure - /// that one Reader does not modify the original luminance source and leave it in an unknown state - /// for other Readers in the chain. - /// - /// dswitkin@google.com (Daniel Switkin) - public abstract class LuminanceSource - { - private int width; - private int height; - - protected LuminanceSource(int width, int height) - { - this.width = width; - this.height = height; - } - - /// - /// Fetches one row of luminance data from the underlying platform's bitmap. Values range from - /// 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have - /// to bitwise and with 0xff for each value. It is preferable for implementations of this method - /// to only fetch this row rather than the whole image, since no 2D Readers may be installed and - /// getMatrix() may never be called. - /// - /// The row to fetch, which must be in [0, bitmap height) - /// An optional preallocated array. If null or too small, it will be ignored. - /// Always use the returned object, and ignore the .length of the array. - /// - /// An array containing the luminance data. - public abstract byte[] getRow(int y, byte[] row); - - /// - /// Fetches luminance data for the underlying bitmap. Values should be fetched using: - /// int luminance = array[y * width + x] & 0xff - /// - /// - /// A row-major 2D array of luminance values. Do not use result.length as it may be - /// larger than width * height bytes on some platforms. Do not modify the contents - /// of the result. - /// - public abstract byte[] Matrix { get; } - - /// The width of the bitmap. - virtual public int Width - { - get - { - return width; - } - protected set - { - width = value; - } - } - - /// The height of the bitmap. - virtual public int Height - { - get - { - return height; - } - protected set - { - height = value; - } - } - - /// Whether this subclass supports cropping. - virtual public bool CropSupported - { - get - { - return false; - } - } - - /// - /// Returns a new object with cropped image data. Implementations may keep a reference to the - /// original data rather than a copy. Only callable if CropSupported is true. - /// - /// The left coordinate, which must be in [0, Width) - /// The top coordinate, which must be in [0, Height) - /// The width of the rectangle to crop. - /// The height of the rectangle to crop. - /// A cropped version of this object. - public virtual LuminanceSource crop(int left, int top, int width, int height) - { - throw new NotSupportedException("This luminance source does not support cropping."); - } - - /// Whether this subclass supports counter-clockwise rotation. - virtual public bool RotateSupported - { - get - { - return false; - } - } - - /// - /// Returns a new object with rotated image data by 90 degrees counterclockwise. - /// Only callable if is true. - /// - /// A rotated version of this object. - public virtual LuminanceSource rotateCounterClockwise() - { - throw new NotSupportedException("This luminance source does not support rotation."); - } - - /// - /// Returns a new object with rotated image data by 45 degrees counterclockwise. - /// Only callable if is true. - /// - /// A rotated version of this object. - public virtual LuminanceSource rotateCounterClockwise45() - { - throw new NotSupportedException("This luminance source does not support rotation by 45 degrees."); - } - - /// - /// - /// Whether this subclass supports invertion. - virtual public bool InversionSupported - { - get - { - return false; - } - } - - virtual public LuminanceSource invert() - { - throw new NotSupportedException("This luminance source does not support inversion."); - } - - override public String ToString() - { - var row = new byte[width]; - var result = new StringBuilder(height * (width + 1)); - for (int y = 0; y < height; y++) - { - row = getRow(y, row); - for (int x = 0; x < width; x++) - { - int luminance = row[x] & 0xFF; - char c; - if (luminance < 0x40) - { - c = '#'; - } - else if (luminance < 0x80) - { - c = '+'; - } - else if (luminance < 0xC0) - { - c = '.'; - } - else - { - c = ' '; - } - result.Append(c); - } - result.Append('\n'); - } - return result.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/MultiFormatReader.cs b/zxing.core/xx/MultiFormatReader.cs deleted file mode 100644 index d58ca6c..0000000 --- a/zxing.core/xx/MultiFormatReader.cs +++ /dev/null @@ -1,228 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Collections.Generic; - -using ZXing.Aztec; -using ZXing.Datamatrix; -using ZXing.IMB; -using ZXing.Maxicode; -using ZXing.OneD; -using ZXing.PDF417; -using ZXing.QrCode; - -namespace ZXing -{ - /// - /// MultiFormatReader is a convenience class and the main entry point into the library for most uses. - /// By default it attempts to decode all barcode formats that the library supports. Optionally, you - /// can provide a hints object to request different behavior, for example only decoding QR codes. - /// - /// Sean Owen - /// dswitkin@google.com (Daniel Switkin) - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - public sealed class MultiFormatReader : Reader - { - private IDictionary hints; - private IList readers; - - /// This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it - /// passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly. - /// Use setHints() followed by decodeWithState() for continuous scan applications. - /// - /// - /// The pixel data to decode - /// - /// The contents of the image - /// - /// ReaderException Any errors which occurred - public Result decode(BinaryBitmap image) - { - Hints = null; - return decodeInternal(image); - } - - /// Decode an image using the hints provided. Does not honor existing state. - /// - /// - /// The pixel data to decode - /// - /// The hints to use, clearing the previous state. - /// - /// The contents of the image - /// - /// ReaderException Any errors which occurred - public Result decode(BinaryBitmap image, IDictionary hints) - { - Hints = hints; - return decodeInternal(image); - } - - /// Decode an image using the state set up by calling setHints() previously. Continuous scan - /// clients will get a large speed increase by using this instead of decode(). - /// - /// - /// The pixel data to decode - /// - /// The contents of the image - /// - /// ReaderException Any errors which occurred - public Result decodeWithState(BinaryBitmap image) - { - // Make sure to set up the default state so we don't crash - if (readers == null) - { - Hints = null; - } - return decodeInternal(image); - } - - /// This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls - /// to decodeWithState(image) can reuse the same set of readers without reallocating memory. This - /// is important for performance in continuous scan clients. - /// - /// - /// The set of hints to use for subsequent calls to decode(image) - /// - public IDictionary Hints - { - set - { - hints = value; - - var tryHarder = value != null && value.ContainsKey(DecodeHintType.TRY_HARDER); - var formats = value == null || !value.ContainsKey(DecodeHintType.POSSIBLE_FORMATS) ? null : (IList)value[DecodeHintType.POSSIBLE_FORMATS]; - - if (formats != null) - { - bool addOneDReader = - formats.Contains(BarcodeFormat.All_1D) || - formats.Contains(BarcodeFormat.UPC_A) || - formats.Contains(BarcodeFormat.UPC_E) || - formats.Contains(BarcodeFormat.EAN_13) || - formats.Contains(BarcodeFormat.EAN_8) || - formats.Contains(BarcodeFormat.CODABAR) || - formats.Contains(BarcodeFormat.CODE_39) || - formats.Contains(BarcodeFormat.CODE_93) || - formats.Contains(BarcodeFormat.CODE_128) || - formats.Contains(BarcodeFormat.ITF) || - formats.Contains(BarcodeFormat.RSS_14) || - formats.Contains(BarcodeFormat.RSS_EXPANDED); - - readers = new List(); - - // Put 1D readers upfront in "normal" mode - if (addOneDReader && !tryHarder) - { - readers.Add(new MultiFormatOneDReader(value)); - } - if (formats.Contains(BarcodeFormat.QR_CODE)) - { - readers.Add(new QRCodeReader()); - } - if (formats.Contains(BarcodeFormat.DATA_MATRIX)) - { - readers.Add(new DataMatrixReader()); - } - if (formats.Contains(BarcodeFormat.AZTEC)) - { - readers.Add(new AztecReader()); - } - if (formats.Contains(BarcodeFormat.PDF_417)) - { - readers.Add(new PDF417Reader()); - } - if (formats.Contains(BarcodeFormat.MAXICODE)) - { - readers.Add(new MaxiCodeReader()); - } - if (formats.Contains(BarcodeFormat.IMB)) - { - readers.Add(new IMBReader()); - } - // At end in "try harder" mode - if (addOneDReader && tryHarder) - { - readers.Add(new MultiFormatOneDReader(value)); - } - } - - if (readers == null || - readers.Count == 0) - { - readers = readers ?? new List(); - - if (!tryHarder) - { - readers.Add(new MultiFormatOneDReader(value)); - } - readers.Add(new QRCodeReader()); - readers.Add(new DataMatrixReader()); - readers.Add(new AztecReader()); - readers.Add(new PDF417Reader()); - readers.Add(new MaxiCodeReader()); - - if (tryHarder) - { - readers.Add(new MultiFormatOneDReader(value)); - } - } - } - } - - public void reset() - { - if (readers != null) - { - foreach (var reader in readers) - { - reader.reset(); - } - } - } - - private Result decodeInternal(BinaryBitmap image) - { - if (readers != null) - { - var rpCallback = hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) - ? (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK] - : null; - - for (var index = 0; index < readers.Count; index++) - { - var reader = readers[index]; - reader.reset(); - var result = reader.decode(image, hints); - if (result != null) - { - // found a barcode, pushing the successful reader up front - // I assume that the same type of barcode is read multiple times - // so the reordering of the readers list should speed up the next reading - // a little bit - readers.RemoveAt(index); - readers.Insert(0, reader); - return result; - } - if (rpCallback != null) - rpCallback(null); - } - } - - return null; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/MultiFormatWriter.cs b/zxing.core/xx/MultiFormatWriter.cs deleted file mode 100644 index 027c8ab..0000000 --- a/zxing.core/xx/MultiFormatWriter.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -using ZXing.Aztec; -using ZXing.Common; -using ZXing.Datamatrix; -using ZXing.OneD; -using ZXing.PDF417; -using ZXing.QrCode; - -namespace ZXing -{ - /// This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat - /// requested and encodes the barcode with the supplied contents. - /// - /// - /// dswitkin@google.com (Daniel Switkin) - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public sealed class MultiFormatWriter : Writer - { - private static readonly IDictionary> formatMap; - - static MultiFormatWriter() - { - formatMap = new Dictionary> - { - {BarcodeFormat.EAN_8, () => new EAN8Writer()}, - {BarcodeFormat.EAN_13, () => new EAN13Writer()}, - {BarcodeFormat.UPC_A, () => new UPCAWriter()}, - {BarcodeFormat.QR_CODE, () => new QRCodeWriter()}, - {BarcodeFormat.CODE_39, () => new Code39Writer()}, - {BarcodeFormat.CODE_128, () => new Code128Writer()}, - {BarcodeFormat.ITF, () => new ITFWriter()}, - {BarcodeFormat.PDF_417, () => new PDF417Writer()}, - {BarcodeFormat.CODABAR, () => new CodaBarWriter()}, - {BarcodeFormat.MSI, () => new MSIWriter()}, - {BarcodeFormat.PLESSEY, () => new PlesseyWriter()}, - {BarcodeFormat.DATA_MATRIX, () => new DataMatrixWriter()}, - {BarcodeFormat.AZTEC, () => new AztecWriter()}, - }; - } - - /// - /// Gets the collection of supported writers. - /// - public static ICollection SupportedWriters - { - get { return formatMap.Keys; } - } - - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - { - return encode(contents, format, width, height, null); - } - - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, IDictionary hints) - { - if (!formatMap.ContainsKey(format)) - throw new ArgumentException("No encoder available for format " + format); - - return formatMap[format]().encode(contents, format, width, height, hints); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/PlanarYUVLuminanceSource.cs b/zxing.core/xx/PlanarYUVLuminanceSource.cs deleted file mode 100644 index a580b7b..0000000 --- a/zxing.core/xx/PlanarYUVLuminanceSource.cs +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing -{ - /// - /// This object extends LuminanceSource around an array of YUV data returned from the camera driver, - /// with the option to crop to a rectangle within the full data. This can be used to exclude - /// superfluous pixels around the perimeter and speed up decoding. - /// It works for any pixel format where the Y channel is planar and appears first, including - /// YCbCr_420_SP and YCbCr_422_SP. - /// @author dswitkin@google.com (Daniel Switkin) - /// - public sealed class PlanarYUVLuminanceSource : BaseLuminanceSource - { - private const int THUMBNAIL_SCALE_FACTOR = 2; - - private readonly byte[] yuvData; - private readonly int dataWidth; - private readonly int dataHeight; - private readonly int left; - private readonly int top; - - /// - /// Initializes a new instance of the class. - /// - /// The yuv data. - /// Width of the data. - /// Height of the data. - /// The left. - /// The top. - /// The width. - /// The height. - /// if set to true [reverse horiz]. - public PlanarYUVLuminanceSource(byte[] yuvData, - int dataWidth, - int dataHeight, - int left, - int top, - int width, - int height, - bool reverseHoriz) - : base(width, height) - { - if (left + width > dataWidth || top + height > dataHeight) - { - throw new ArgumentException("Crop rectangle does not fit within image data."); - } - - this.yuvData = yuvData; - this.dataWidth = dataWidth; - this.dataHeight = dataHeight; - this.left = left; - this.top = top; - if (reverseHoriz) - { - reverseHorizontal(width, height); - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The luminances. - /// The width. - /// The height. - private PlanarYUVLuminanceSource(byte[] luminances, int width, int height) - : base(width, height) - { - yuvData = luminances; - this.luminances = luminances; - dataWidth = width; - dataHeight = height; - left = 0; - top = 0; - } - - /// - /// Fetches one row of luminance data from the underlying platform's bitmap. Values range from - /// 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have - /// to bitwise and with 0xff for each value. It is preferable for implementations of this method - /// to only fetch this row rather than the whole image, since no 2D Readers may be installed and - /// getMatrix() may never be called. - /// - /// The row to fetch, 0 <= y < Height. - /// An optional preallocated array. If null or too small, it will be ignored. - /// Always use the returned object, and ignore the .length of the array. - /// - /// An array containing the luminance data. - /// - override public byte[] getRow(int y, byte[] row) - { - if (y < 0 || y >= Height) - { - throw new ArgumentException("Requested row is outside the image: " + y); - } - int width = Width; - if (row == null || row.Length < width) - { - row = new byte[width]; - } - int offset = (y + top) * dataWidth + left; - Array.Copy(yuvData, offset, row, 0, width); - return row; - } - - /// - /// - /// - override public byte[] Matrix - { - get - { - int width = Width; - int height = Height; - - // If the caller asks for the entire underlying image, save the copy and give them the - // original data. The docs specifically warn that result.length must be ignored. - if (width == dataWidth && height == dataHeight) - { - return yuvData; - } - - int area = width * height; - byte[] matrix = new byte[area]; - int inputOffset = top * dataWidth + left; - - // If the width matches the full width of the underlying data, perform a single copy. - if (width == dataWidth) - { - Array.Copy(yuvData, inputOffset, matrix, 0, area); - return matrix; - } - - // Otherwise copy one cropped row at a time. - byte[] yuv = yuvData; - for (int y = 0; y < height; y++) - { - int outputOffset = y * width; - Array.Copy(yuv, inputOffset, matrix, outputOffset, width); - inputOffset += dataWidth; - } - return matrix; - } - } - - /// - /// - /// Whether this subclass supports cropping. - override public bool CropSupported - { - get { return true; } - } - - /// - /// Returns a new object with cropped image data. Implementations may keep a reference to the - /// original data rather than a copy. Only callable if CropSupported is true. - /// - /// The left coordinate, 0 <= left < Width. - /// The top coordinate, 0 <= top <= Height. - /// The width of the rectangle to crop. - /// The height of the rectangle to crop. - /// - /// A cropped version of this object. - /// - override public LuminanceSource crop(int left, int top, int width, int height) - { - return new PlanarYUVLuminanceSource(yuvData, - dataWidth, - dataHeight, - this.left + left, - this.top + top, - width, - height, - false); - } - - /// - /// Renders the cropped greyscale bitmap. - /// - /// - public int[] renderThumbnail() - { - int width = Width / THUMBNAIL_SCALE_FACTOR; - int height = Height / THUMBNAIL_SCALE_FACTOR; - int[] pixels = new int[width * height]; - byte[] yuv = yuvData; - int inputOffset = top * dataWidth + left; - - for (int y = 0; y < height; y++) - { - int outputOffset = y * width; - for (int x = 0; x < width; x++) - { - int grey = yuv[inputOffset + x * THUMBNAIL_SCALE_FACTOR] & 0xff; - pixels[outputOffset + x] = ((0x00FF0000 << 8) | (grey * 0x00010101)); - } - inputOffset += dataWidth * THUMBNAIL_SCALE_FACTOR; - } - return pixels; - } - - /// - /// width of image from {@link #renderThumbnail()} - /// - public int ThumbnailWidth - { - get - { - return Width / THUMBNAIL_SCALE_FACTOR; - } - } - - /// - /// height of image from {@link #renderThumbnail()} - /// - public int ThumbnailHeight - { - get - { - return Height / THUMBNAIL_SCALE_FACTOR; - } - } - - private void reverseHorizontal(int width, int height) - { - byte[] yuvData = this.yuvData; - for (int y = 0, rowStart = top * dataWidth + left; y < height; y++, rowStart += dataWidth) - { - int middle = rowStart + width / 2; - for (int x1 = rowStart, x2 = rowStart + width - 1; x1 < middle; x1++, x2--) - { - byte temp = yuvData[x1]; - yuvData[x1] = yuvData[x2]; - yuvData[x2] = temp; - } - } - } - - protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height) - { - return new PlanarYUVLuminanceSource(newLuminances, width, height); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/RGB565LuminanceSource.cs b/zxing.core/xx/RGB565LuminanceSource.cs deleted file mode 100644 index 284752b..0000000 --- a/zxing.core/xx/RGB565LuminanceSource.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* -* 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 -{ - /// - /// - /// - [Obsolete("Use RGBLuminanceSource with the argument BitmapFormat.RGB565")] - public class RGB565LuminanceSource :RGBLuminanceSource - { - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The height. - protected RGB565LuminanceSource(int width, int height) - : base(width, height) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The RGB565 raw data. - /// The width. - /// The height. - public RGB565LuminanceSource(byte[] rgb565RawData, int width, int height) - : base(rgb565RawData, width, height, BitmapFormat.RGB565) - { - } - - /// - /// Should create a new luminance source with the right class type. - /// The method is used in methods crop and rotate. - /// - /// The new luminances. - /// The width. - /// The height. - /// - protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height) - { - return new RGB565LuminanceSource(width, height) { luminances = newLuminances }; - } - } -} diff --git a/zxing.core/xx/RGBLuminanceSource.cs b/zxing.core/xx/RGBLuminanceSource.cs deleted file mode 100644 index 5d24ade..0000000 --- a/zxing.core/xx/RGBLuminanceSource.cs +++ /dev/null @@ -1,314 +0,0 @@ -/* -* 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 -{ - /// - /// Luminance source class which support different formats of images. - /// - public partial class RGBLuminanceSource : BaseLuminanceSource - { - /// - /// enumeration of supported bitmap format which the RGBLuminanceSource can process - /// - public enum BitmapFormat - { - /// - /// format of the byte[] isn't known. RGBLuminanceSource tries to determine the best possible value - /// - Unknown, - /// - /// grayscale array, the byte array is a luminance array with 1 byte per pixel - /// - Gray8, - /// - /// 3 bytes per pixel with the channels red, green and blue - /// - RGB24, - /// - /// 4 bytes per pixel with the channels red, green and blue - /// - RGB32, - /// - /// 4 bytes per pixel with the channels alpha, red, green and blue - /// - ARGB32, - /// - /// 3 bytes per pixel with the channels blue, green and red - /// - BGR24, - /// - /// 4 bytes per pixel with the channels blue, green and red - /// - BGR32, - /// - /// 4 bytes per pixel with the channels blue, green, red and alpha - /// - BGRA32, - /// - /// 2 bytes per pixel, 5 bit red, 6 bits green and 5 bits blue - /// - RGB565, - /// - /// 4 bytes per pixel with the channels red, green, blue and alpha - /// - RGBA32, - } - - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The height. - protected RGBLuminanceSource(int width, int height) - : base(width, height) - { - } - - /// - /// Initializes a new instance of the class. - /// It supports a byte array with 3 bytes per pixel (RGB24). - /// - /// The RGB raw bytes. - /// The width. - /// The height. - public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height) - : this(rgbRawBytes, width, height, BitmapFormat.RGB24) - { - } - - /// - /// Initializes a new instance of the class. - /// It supports a byte array with 1 byte per pixel (Gray8). - /// That means the whole array consists of the luminance values (grayscale). - /// - /// The luminance array. - /// The width. - /// The height. - /// if set to true [is8 bit]. - [Obsolete("Use RGBLuminanceSource(luminanceArray, width, height, BitmapFormat.Gray8)")] - public RGBLuminanceSource(byte[] luminanceArray, int width, int height, bool is8Bit) - : this(luminanceArray, width, height, BitmapFormat.Gray8) - { - } - - /// - /// Initializes a new instance of the class. - /// It supports a byte array with 3 bytes per pixel (RGB24). - /// - /// The RGB raw bytes. - /// The width. - /// The height. - /// The bitmap format. - public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height, BitmapFormat bitmapFormat) - : base(width, height) - { - CalculateLuminance(rgbRawBytes, bitmapFormat); - } - - /// - /// Should create a new luminance source with the right class type. - /// The method is used in methods crop and rotate. - /// - /// The new luminances. - /// The width. - /// The height. - /// - 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)); - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/Reader.cs b/zxing.core/xx/Reader.cs deleted file mode 100644 index 95ca6db..0000000 --- a/zxing.core/xx/Reader.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Collections.Generic; - -namespace ZXing -{ - /// - /// Implementations of this interface can decode an image of a barcode in some format into - /// the String it encodes. For example, can - /// decode a QR code. The decoder may optionally receive hints from the caller which may help - /// it decode more quickly or accurately. - /// - /// See , which attempts to determine what barcode - /// format is present within the image as well, and then decodes it accordingly. - /// - /// Sean Owen - /// dswitkin@google.com (Daniel Switkin) - public interface Reader - { - /// - /// Locates and decodes a barcode in some format within an image. - /// - /// image of barcode to decode - /// String which the barcode encodes - Result decode(BinaryBitmap image); - - /// Locates and decodes a barcode in some format within an image. This method also accepts - /// hints, each possibly associated to some data, which may help the implementation decode. - /// - /// image of barcode to decode - /// passed as a from - /// to arbitrary data. The - /// meaning of the data depends upon the hint type. The implementation may or may not do - /// anything with these hints. - /// - /// String which the barcode encodes - Result decode(BinaryBitmap image, IDictionary hints); - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - void reset(); - } -} \ No newline at end of file diff --git a/zxing.core/xx/ReaderException.cs b/zxing.core/xx/ReaderException.cs deleted file mode 100644 index 586fafb..0000000 --- a/zxing.core/xx/ReaderException.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing -{ - /// - /// The general exception class throw when something goes wrong during decoding of a barcode. - /// This includes, but is not limited to, failing checksums / error correction algorithms, being - /// unable to locate finder timing patterns, and so on. - /// - /// Sean Owen - public class ReaderException : Exception - { - /// - /// Gets the instance. - /// - public static ReaderException Instance - { - get - { - return new ReaderException(); - } - - } - - /// - /// Initializes a new instance of the class. - /// - protected ReaderException() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The inner exception. - protected ReaderException(Exception innerException) - : base(innerException.Message, innerException) - { - } - } -} diff --git a/zxing.core/xx/Result.cs b/zxing.core/xx/Result.cs deleted file mode 100644 index c1ceb59..0000000 --- a/zxing.core/xx/Result.cs +++ /dev/null @@ -1,161 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -namespace ZXing -{ - /// - /// Encapsulates the result of decoding a barcode within an image. - /// - public sealed class Result - { - /// raw text encoded by the barcode, if applicable, otherwise null - public String Text { get; private set; } - - /// raw bytes encoded by the barcode, if applicable, otherwise null - public byte[] RawBytes { get; private set; } - - /// - /// points related to the barcode in the image. These are typically points - /// identifying finder patterns or the corners of the barcode. The exact meaning is - /// specific to the type of barcode that was decoded. - /// - public ResultPoint[] ResultPoints { get; private set; } - - /// {@link BarcodeFormat} representing the format of the barcode that was decoded - public BarcodeFormat BarcodeFormat { get; private set; } - - /// - /// {@link Hashtable} mapping {@link ResultMetadataType} keys to values. May be - /// null. This contains optional metadata about what was detected about the barcode, - /// like orientation. - /// - public IDictionary ResultMetadata { get; private set; } - - /// - /// Gets the timestamp. - /// - public long Timestamp { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The text. - /// The raw bytes. - /// The result points. - /// The format. - public Result(String text, - byte[] rawBytes, - ResultPoint[] resultPoints, - BarcodeFormat format) - : this(text, rawBytes, resultPoints, format, DateTime.Now.Ticks) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The text. - /// The raw bytes. - /// The result points. - /// The format. - /// The timestamp. - public Result(String text, byte[] rawBytes, ResultPoint[] resultPoints, BarcodeFormat format, long timestamp) - { - if (text == null && rawBytes == null) - { - throw new ArgumentException("Text and bytes are null"); - } - Text = text; - RawBytes = rawBytes; - ResultPoints = resultPoints; - BarcodeFormat = format; - ResultMetadata = null; - Timestamp = timestamp; - } - - /// - /// Adds one metadata to the result - /// - /// The type. - /// The value. - public void putMetadata(ResultMetadataType type, Object value) - { - if (ResultMetadata == null) - { - ResultMetadata = new Dictionary(); - } - ResultMetadata[type] = value; - } - - /// - /// Adds a list of metadata to the result - /// - /// The metadata. - public void putAllMetadata(IDictionary metadata) - { - if (metadata != null) - { - if (ResultMetadata == null) - { - ResultMetadata = metadata; - } - else - { - foreach (var entry in metadata) - ResultMetadata[entry.Key] = entry.Value; - } - } - } - - /// - /// Adds the result points. - /// - /// The new points. - public void addResultPoints(ResultPoint[] newPoints) - { - var oldPoints = ResultPoints; - if (oldPoints == null) - { - ResultPoints = newPoints; - } - else if (newPoints != null && newPoints.Length > 0) - { - var allPoints = new ResultPoint[oldPoints.Length + newPoints.Length]; - Array.Copy(oldPoints, 0, allPoints, 0, oldPoints.Length); - Array.Copy(newPoints, 0, allPoints, oldPoints.Length, newPoints.Length); - ResultPoints = allPoints; - } - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - if (Text == null) - { - return "[" + RawBytes.Length + " bytes]"; - } - return Text; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/ResultMetadataType.cs b/zxing.core/xx/ResultMetadataType.cs deleted file mode 100644 index 4543278..0000000 --- a/zxing.core/xx/ResultMetadataType.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace ZXing -{ - /// - /// Represents some type of metadata about the result of the decoding that the decoder - /// wishes to communicate back to the caller. - /// - /// Sean Owen - public enum ResultMetadataType - { - /// - /// Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. - /// - OTHER, - - /// - /// Denotes the likely approximate orientation of the barcode in the image. This value - /// is given as degrees rotated clockwise from the normal, upright orientation. - /// For example a 1D barcode which was found by reading top-to-bottom would be - /// said to have orientation "90". This key maps to an {@link Integer} whose - /// value is in the range [0,360). - /// - ORIENTATION, - - /// - ///

2D barcode formats typically encode text, but allow for a sort of 'byte mode' - /// which is sometimes used to encode binary data. While {@link Result} makes available - /// the complete raw bytes in the barcode for these formats, it does not offer the bytes - /// from the byte segments alone.

- ///

This maps to a {@link java.util.List} of byte arrays corresponding to the - /// raw bytes in the byte segments in the barcode, in order.

- ///
- BYTE_SEGMENTS, - - /// - /// Error correction level used, if applicable. The value type depends on the - /// format, but is typically a String. - /// - ERROR_CORRECTION_LEVEL, - - /// - /// For some periodicals, indicates the issue number as an {@link Integer}. - /// - ISSUE_NUMBER, - - /// - /// For some products, indicates the suggested retail price in the barcode as a - /// formatted {@link String}. - /// - SUGGESTED_PRICE, - - /// - /// For some products, the possible country of manufacture as a {@link String} denoting the - /// ISO country code. Some map to multiple possible countries, like "US/CA". - /// - POSSIBLE_COUNTRY, - - /// - /// For some products, the extension text - /// - UPC_EAN_EXTENSION, - - /// - /// If the code format supports structured append and - /// the current scanned code is part of one then the - /// sequence number is given with it. - /// - STRUCTURED_APPEND_SEQUENCE, - - /// - /// If the code format supports structured append and - /// the current scanned code is part of one then the - /// parity is given with it. - /// - STRUCTURED_APPEND_PARITY, - - /// - /// PDF417-specific metadata - /// - PDF417_EXTRA_METADATA, - - /// - /// Aztec-specific metadata - /// - AZTEC_EXTRA_METADATA - } -} \ No newline at end of file diff --git a/zxing.core/xx/ResultPoint.cs b/zxing.core/xx/ResultPoint.cs deleted file mode 100644 index a134702..0000000 --- a/zxing.core/xx/ResultPoint.cs +++ /dev/null @@ -1,196 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -using ZXing.Common.Detector; - -namespace ZXing -{ - /// - /// Encapsulates a point of interest in an image containing a barcode. Typically, this - /// would be the location of a finder pattern or the corner of the barcode, for example. - /// - /// Sean Owen - public class ResultPoint - { - private readonly float x; - private readonly float y; - private readonly byte[] bytesX; - private readonly byte[] bytesY; - private String toString; - - /// - /// Initializes a new instance of the class. - /// - public ResultPoint() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The x. - /// The y. - public ResultPoint(float x, float y) - { - this.x = x; - this.y = y; - // calculate only once for GetHashCode - bytesX = BitConverter.GetBytes(x); - bytesY = BitConverter.GetBytes(y); - } - - /// - /// Gets the X. - /// - virtual public float X - { - get - { - return x; - } - } - - /// - /// Gets the Y. - /// - virtual public float Y - { - get - { - return y; - } - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(Object other) - { - var otherPoint = other as ResultPoint; - if (otherPoint == null) - return false; - return x == otherPoint.x && y == otherPoint.y; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - return 31 * ((bytesX[0] << 24) + (bytesX[1] << 16) + (bytesX[2] << 8) + bytesX[3]) + - (bytesY[0] << 24) + (bytesY[1] << 16) + (bytesY[2] << 8) + bytesY[3]; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - if (toString == null) - { - var result = new System.Text.StringBuilder(25); - result.AppendFormat(System.Globalization.CultureInfo.CurrentUICulture, "({0}, {1})", x, y); - toString = result.ToString(); - } - return toString; - } - - /// - /// Orders an array of three ResultPoints in an order [A,B,C] such that AB is less than AC and - /// BC is less than AC and the angle between BC and BA is less than 180 degrees. - /// - /// array of three to order - public static void orderBestPatterns(ResultPoint[] patterns) - { - // Find distances between pattern centers - float zeroOneDistance = distance(patterns[0], patterns[1]); - float oneTwoDistance = distance(patterns[1], patterns[2]); - float zeroTwoDistance = distance(patterns[0], patterns[2]); - - ResultPoint pointA, pointB, pointC; - // Assume one closest to other two is B; A and C will just be guesses at first - if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) - { - pointB = patterns[0]; - pointA = patterns[1]; - pointC = patterns[2]; - } - else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) - { - pointB = patterns[1]; - pointA = patterns[0]; - pointC = patterns[2]; - } - else - { - pointB = patterns[2]; - pointA = patterns[0]; - pointC = patterns[1]; - } - - // Use cross product to figure out whether A and C are correct or flipped. - // This asks whether BC x BA has a positive z component, which is the arrangement - // we want for A, B, C. If it's negative, then we've got it flipped around and - // should swap A and C. - if (crossProductZ(pointA, pointB, pointC) < 0.0f) - { - ResultPoint temp = pointA; - pointA = pointC; - pointC = temp; - } - - patterns[0] = pointA; - patterns[1] = pointB; - patterns[2] = pointC; - } - - - /// - /// calculates the distance between two points - /// - /// first pattern - /// second pattern - /// - /// distance between two points - /// - public static float distance(ResultPoint pattern1, ResultPoint pattern2) - { - return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y); - } - - /// - /// Returns the z component of the cross product between vectors BC and BA. - /// - private static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC) - { - float bX = pointB.x; - float bY = pointB.y; - return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX)); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/ResultPointCallback.cs b/zxing.core/xx/ResultPointCallback.cs deleted file mode 100644 index aa5a0d0..0000000 --- a/zxing.core/xx/ResultPointCallback.cs +++ /dev/null @@ -1,26 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing -{ - /// Callback which is invoked when a possible result point (significant - /// point in the barcode image such as a corner) is found. - /// - /// - /// - /// - public delegate void ResultPointCallback(ResultPoint point); -} \ No newline at end of file diff --git a/zxing.core/xx/SupportClass.cs b/zxing.core/xx/SupportClass.cs deleted file mode 100644 index 0b4aff6..0000000 --- a/zxing.core/xx/SupportClass.cs +++ /dev/null @@ -1,175 +0,0 @@ -// -// In order to convert some functionality to Visual C#, the Java Language Conversion Assistant -// creates "support classes" that duplicate the original functionality. -// -// Support classes replicate the functionality of the original code, but in some cases they are -// substantially different architecturally. Although every effort is made to preserve the -// original architecture of the application in the converted project, the user should be aware that -// the primary goal of these support classes is to replicate functionality, and that at times -// the architecture of the resulting solution may differ somewhat. -// - -using System; -using System.Collections.Generic; -using System.Text; - -namespace ZXing -{ - /// - /// Contains conversion support elements such as classes, interfaces and static methods. - /// - public static class SupportClass - { - /*******************************/ - /// - /// Copies an array of chars obtained from a String into a specified array of chars - /// - /// The String to get the chars from - /// Position of the String to start getting the chars - /// Position of the String to end getting the chars - /// Array to return the chars - /// Position of the destination array of chars to start storing the chars - /// An array of chars - public static void GetCharsFromString(System.String sourceString, int sourceStart, int sourceEnd, char[] destinationArray, int destinationStart) - { - int sourceCounter = sourceStart; - int destinationCounter = destinationStart; - while (sourceCounter < sourceEnd) - { - destinationArray[destinationCounter] = (char)sourceString[sourceCounter]; - sourceCounter++; - destinationCounter++; - } - } - - /*******************************/ - /// - /// Sets the capacity for the specified List - /// - /// The List which capacity will be set - /// The new capacity value - public static void SetCapacity(System.Collections.Generic.IList vector, int newCapacity) where T : new() - { - while (newCapacity > vector.Count) - vector.Add(new T()); - while (newCapacity < vector.Count) - vector.RemoveAt(vector.Count - 1); - } - - /// - /// Converts a string-Collection to an array - /// - /// The strings. - /// - public static String[] toStringArray(ICollection strings) - { - var result = new String[strings.Count]; - strings.CopyTo(result, 0); - return result; - } - - /// - /// Joins all elements to one string. - /// - /// - /// The separator. - /// The values. - /// - public static string Join(string separator, IEnumerable values) - { - var builder = new StringBuilder(); - separator = separator ?? String.Empty; - if (values != null) - { - foreach (var value in values) - { - builder.Append(value); - builder.Append(separator); - } - if (builder.Length > 0) - builder.Length -= separator.Length; - } - - return builder.ToString(); - } - - /// - /// Fills the specified array. - /// (can't use extension method because of .Net 2.0 support) - /// - /// - /// The array. - /// The value. - public static void Fill(T[] array, T value) - { - for (int i = 0; i < array.Length; i++) - { - array[i] = value; - } - } - - /// - /// Fills the specified array. - /// (can't use extension method because of .Net 2.0 support) - /// - /// - /// The array. - /// The start index. - /// The end index. - /// The value. - public static void Fill(T[] array, int startIndex, int endIndex, T value) - { - for (int i = startIndex; i < endIndex; i++) - { - array[i] = value; - } - } - - public static string ToBinaryString(int x) - { - char[] bits = new char[32]; - int i = 0; - - while (x != 0) - { - bits[i++] = (x & 1) == 1 ? '1' : '0'; - x >>= 1; - } - - Array.Reverse(bits, 0, i); - return new string(bits); - } - - public static int bitCount(int n) - { - int ret = 0; - while (n != 0) - { - n &= (n - 1); - ret++; - } - return ret; - } - - /// - /// Savely gets the value of a decoding hint - /// if hints is null the default is returned - /// - /// - /// The hints. - /// Type of the hint. - /// The @default. - /// - public static T GetValue(IDictionary hints, DecodeHintType hintType, T @default) - { - // can't use extension method because of .Net 2.0 support - - if (hints == null) - return @default; - if (!hints.ContainsKey(hintType)) - return @default; - - return (T)hints[hintType]; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/Writer.cs b/zxing.core/xx/Writer.cs deleted file mode 100644 index 5fa47d4..0000000 --- a/zxing.core/xx/Writer.cs +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing -{ - /// The base class for all objects which encode/generate a barcode image. - /// - /// - /// dswitkin@google.com (Daniel Switkin) - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public interface Writer - { - /// - /// Encode a barcode using the default settings. - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - BitMatrix encode(System.String contents, BarcodeFormat format, int width, int height); - - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// Additional parameters to supply to the encoder - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - BitMatrix encode(String contents, BarcodeFormat format, int width, int height, IDictionary hints); - } -} \ No newline at end of file diff --git a/zxing.core/xx/WriterException.cs b/zxing.core/xx/WriterException.cs deleted file mode 100644 index 027112f..0000000 --- a/zxing.core/xx/WriterException.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing -{ - /// - /// A base class which covers the range of exceptions which may occur when encoding a barcode using - /// the Writer framework. - /// - /// dswitkin@google.com (Daniel Switkin) - public sealed class WriterException : Exception - { - /// - /// Initializes a new instance of the class. - /// - public WriterException() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The message. - public WriterException(String message) - :base(message) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The message. - /// The inner exc. - public WriterException(String message, Exception innerExc) - : base(message, innerExc) - { - } - } -} diff --git a/zxing.core/xx/aztec/AztecDetectorResult.cs b/zxing.core/xx/aztec/AztecDetectorResult.cs deleted file mode 100644 index 14157c1..0000000 --- a/zxing.core/xx/aztec/AztecDetectorResult.cs +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using ZXing.Common; - -namespace ZXing.Aztec.Internal -{ - /// - /// The class contains all information about the Aztec code which was found - /// - public class AztecDetectorResult : DetectorResult - { - /// - /// Gets a value indicating whether this Aztec code is compact. - /// - /// - /// true if compact; otherwise, false. - /// - public bool Compact { get; private set; } - /// - /// Gets the nb datablocks. - /// - public int NbDatablocks { get; private set; } - /// - /// Gets the nb layers. - /// - public int NbLayers { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The bits. - /// The points. - /// if set to true [compact]. - /// The nb datablocks. - /// The nb layers. - public AztecDetectorResult(BitMatrix bits, - ResultPoint[] points, - bool compact, - int nbDatablocks, - int nbLayers) - : base(bits, points) - { - Compact = compact; - NbDatablocks = nbDatablocks; - NbLayers = nbLayers; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/AztecReader.cs b/zxing.core/xx/aztec/AztecReader.cs deleted file mode 100644 index a17bfd1..0000000 --- a/zxing.core/xx/aztec/AztecReader.cs +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Aztec.Internal; - -namespace ZXing.Aztec -{ - /// - /// This implementation can detect and decode Aztec codes in an image. - /// - /// David Olivier - public class AztecReader : Reader - { - /// - /// Locates and decodes a barcode in some format within an image. - /// - /// image of barcode to decode - /// - /// a String representing the content encoded by the Data Matrix code - /// - public Result decode(BinaryBitmap image) - { - return decode(image, null); - } - - /// - /// Locates and decodes a Data Matrix code in an image. - /// - /// image of barcode to decode - /// passed as a {@link java.util.Hashtable} from {@link com.google.zxing.DecodeHintType} - /// to arbitrary data. The - /// meaning of the data depends upon the hint type. The implementation may or may not do - /// anything with these hints. - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image, IDictionary hints) - { - var blackmatrix = image.BlackMatrix; - if (blackmatrix == null) - return null; - - Detector detector = new Detector(blackmatrix); - ResultPoint[] points = null; - DecoderResult decoderResult = null; - - var detectorResult = detector.detect(false); - if (detectorResult != null) - { - points = detectorResult.Points; - - decoderResult = new Decoder().decode(detectorResult); - } - if (decoderResult == null) - { - detectorResult = detector.detect(true); - if (detectorResult == null) - return null; - - points = detectorResult.Points; - decoderResult = new Decoder().decode(detectorResult); - if (decoderResult == null) - return null; - } - - if (hints != null && - hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) - { - var rpcb = (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - if (rpcb != null) - { - foreach (var point in points) - { - rpcb(point); - } - } - } - - var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.AZTEC); - - IList byteSegments = decoderResult.ByteSegments; - if (byteSegments != null) - { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - var ecLevel = decoderResult.ECLevel; - if (ecLevel != null) - { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - - result.putMetadata(ResultMetadataType.AZTEC_EXTRA_METADATA, - new AztecResultMetadata(detectorResult.Compact, detectorResult.NbDatablocks, detectorResult.NbLayers)); - - return result; - } - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - public void reset() - { - // do nothing - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/AztecResultMetadata.cs b/zxing.core/xx/aztec/AztecResultMetadata.cs deleted file mode 100644 index 5df2517..0000000 --- a/zxing.core/xx/aztec/AztecResultMetadata.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2013 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.Aztec -{ - /// - /// Aztec result meta data. - /// - public sealed class AztecResultMetadata - { - /// - /// Gets a value indicating whether this Aztec code is compact. - /// - /// - /// true if compact; otherwise, false. - /// - public bool Compact { get; private set; } - /// - /// Gets the nb datablocks. - /// - public int Datablocks { get; private set; } - /// - /// Gets the nb layers. - /// - public int Layers { get; private set; } - - /// - /// - /// - /// - /// - /// - public AztecResultMetadata(bool compact, int datablocks, int layers) - { - Compact = compact; - Datablocks = datablocks; - Layers = layers; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/AztecWriter.cs b/zxing.core/xx/aztec/AztecWriter.cs deleted file mode 100644 index 52f48da..0000000 --- a/zxing.core/xx/aztec/AztecWriter.cs +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2013 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; - -using ZXing.Aztec.Internal; -using ZXing.Common; - -namespace ZXing.Aztec -{ - /// - /// Generates Aztec 2D barcodes. - /// - public sealed class AztecWriter : Writer - { - private static readonly Encoding DEFAULT_CHARSET; - - static AztecWriter() - { -#if !(WindowsCE || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE) - DEFAULT_CHARSET = Encoding.GetEncoding("ISO-8859-1"); -#elif WindowsCE - try - { - DEFAULT_CHARSET = Encoding.GetEncoding("ISO-8859-1"); - } - catch (PlatformNotSupportedException) - { - DEFAULT_CHARSET = Encoding.GetEncoding(1252); - } -#else - // not fully correct but what else - DEFAULT_CHARSET = Encoding.GetEncoding("UTF-8"); -#endif - } - - /// - /// Encode a barcode using the default settings. - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - /// - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - { - return encode(contents, format, width, height, null); - } - - /// - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// Additional parameters to supply to the encoder - /// - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - /// - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, IDictionary hints) - { - var charset = DEFAULT_CHARSET; - int eccPercent = Internal.Encoder.DEFAULT_EC_PERCENT; - int layers = Internal.Encoder.DEFAULT_AZTEC_LAYERS; - - if (hints != null) - { - if (hints.ContainsKey(EncodeHintType.CHARACTER_SET)) - { - object charsetname = hints[EncodeHintType.CHARACTER_SET]; - if (charsetname != null) - { - charset = Encoding.GetEncoding(charsetname.ToString()); - } - } - if (hints.ContainsKey(EncodeHintType.ERROR_CORRECTION)) - { - object eccPercentObject = hints[EncodeHintType.ERROR_CORRECTION]; - if (eccPercentObject != null) - { - eccPercent = Convert.ToInt32(eccPercentObject); - } - } - if (hints.ContainsKey(EncodeHintType.AZTEC_LAYERS)) - { - object layersObject = hints[EncodeHintType.AZTEC_LAYERS]; - if (layersObject != null) - { - layers = Convert.ToInt32(layersObject); - } - } - } - - return encode(contents, - format, - width, - height, - charset, - eccPercent, - layers); - } - - private static BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Encoding charset, int eccPercent, int layers) - { - if (format != BarcodeFormat.AZTEC) - { - throw new ArgumentException("Can only encode AZTEC code, but got " + format); - } - var aztec = Internal.Encoder.encode(charset.GetBytes(contents), eccPercent, layers); - return renderResult(aztec, width, height); - } - - private static BitMatrix renderResult(AztecCode code, int width, int height) - { - var input = code.Matrix; - if (input == null) - { - throw new InvalidOperationException("No input code matrix"); - } - - int inputWidth = input.Width; - int inputHeight = input.Height; - int outputWidth = Math.Max(width, inputWidth); - int outputHeight = Math.Max(height, inputHeight); - - int multiple = Math.Min(outputWidth / inputWidth, outputHeight / inputHeight); - int leftPadding = (outputWidth - (inputWidth * multiple)) / 2; - int topPadding = (outputHeight - (inputHeight * multiple)) / 2; - - var output = new BitMatrix(outputWidth, outputHeight); - - for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) - { - // Write the contents of this row of the barcode - for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) - { - if (input[inputX, inputY]) - { - output.setRegion(outputX, outputY, multiple, multiple); - } - } - } - - return output; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/decoder/Decoder.cs b/zxing.core/xx/aztec/decoder/Decoder.cs deleted file mode 100644 index 9d4cc71..0000000 --- a/zxing.core/xx/aztec/decoder/Decoder.cs +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -using ZXing.Common; -using ZXing.Common.ReedSolomon; - -namespace ZXing.Aztec.Internal -{ - /// - /// The main class which implements Aztec Code decoding -- as opposed to locating and extracting - /// the Aztec Code from an image. - /// - /// David Olivier - public sealed class Decoder - { - private enum Table - { - UPPER, - LOWER, - MIXED, - DIGIT, - PUNCT, - BINARY - } - - private static readonly String[] UPPER_TABLE = - { - "CTRL_PS", " ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", - "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "CTRL_LL", "CTRL_ML", "CTRL_DL", "CTRL_BS" - }; - - private static readonly String[] LOWER_TABLE = - { - "CTRL_PS", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", - "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "CTRL_US", "CTRL_ML", "CTRL_DL", "CTRL_BS" - }; - - private static readonly String[] MIXED_TABLE = - { - "CTRL_PS", " ", "\x1", "\x2", "\x3", "\x4", "\x5", "\x6", "\x7", "\b", "\t", "\n", - "\xD", "\f", "\r", "\x21", "\x22", "\x23", "\x24", "\x25", "@", "\\", "^", "_", - "`", "|", "~", "\xB1", "CTRL_LL", "CTRL_UL", "CTRL_PL", "CTRL_BS" - }; - - private static readonly String[] PUNCT_TABLE = - { - "", "\r", "\r\n", ". ", ", ", ": ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", - "*", "+", ",", "-", ".", "/", ":", ";", "<", "=", ">", "?", "[", "]", "{", "}", "CTRL_UL" - }; - - private static readonly String[] DIGIT_TABLE = - { - "CTRL_PS", " ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", ".", "CTRL_UL", "CTRL_US" - }; - - private static readonly IDictionary codeTables = new Dictionary - { - {Table.UPPER, UPPER_TABLE}, - {Table.LOWER, LOWER_TABLE}, - {Table.MIXED, MIXED_TABLE}, - {Table.PUNCT, PUNCT_TABLE}, - {Table.DIGIT, DIGIT_TABLE}, - {Table.BINARY, null} - }; - - private static readonly IDictionary codeTableMap = new Dictionary - { - {'U', Table.UPPER}, - {'L', Table.LOWER}, - {'M', Table.MIXED}, - {'P', Table.PUNCT}, - {'D', Table.DIGIT}, - {'B', Table.BINARY} - }; - - private AztecDetectorResult ddata; - - /// - /// Decodes the specified detector result. - /// - /// The detector result. - /// - public DecoderResult decode(AztecDetectorResult detectorResult) - { - ddata = detectorResult; - BitMatrix matrix = detectorResult.Bits; - bool[] rawbits = extractBits(matrix); - if (rawbits == null) - return null; - - bool[] correctedBits = correctBits(rawbits); - if (correctedBits == null) - return null; - - String result = getEncodedData(correctedBits); - if (result == null) - return null; - - return new DecoderResult(null, result, null, null); - } - - // This method is used for testing the high-level encoder - public static String highLevelDecode(bool[] correctedBits) - { - return getEncodedData(correctedBits); - } - - /// - /// Gets the string encoded in the aztec code bits - /// - /// The corrected bits. - /// the decoded string - private static String getEncodedData(bool[] correctedBits) - { - var endIndex = correctedBits.Length; - var latchTable = Table.UPPER; // table most recently latched to - var shiftTable = Table.UPPER; // table to use for the next read - var strTable = UPPER_TABLE; - var result = new StringBuilder(20); - var index = 0; - - while (index < endIndex) - { - if (shiftTable == Table.BINARY) - { - if (endIndex - index < 5) - { - break; - } - int length = readCode(correctedBits, index, 5); - index += 5; - if (length == 0) - { - if (endIndex - index < 11) - { - break; - } - length = readCode(correctedBits, index, 11) + 31; - index += 11; - } - for (int charCount = 0; charCount < length; charCount++) - { - if (endIndex - index < 8) - { - index = endIndex; // Force outer loop to exit - break; - } - int code = readCode(correctedBits, index, 8); - result.Append((char) code); - index += 8; - } - // Go back to whatever mode we had been in - shiftTable = latchTable; - strTable = codeTables[shiftTable]; - } - else - { - int size = shiftTable == Table.DIGIT ? 4 : 5; - if (endIndex - index < size) - { - break; - } - int code = readCode(correctedBits, index, size); - index += size; - String str = getCharacter(strTable, code); - if (str.StartsWith("CTRL_")) - { - // Table changes - shiftTable = getTable(str[5]); - strTable = codeTables[shiftTable]; - if (str[6] == 'L') - { - latchTable = shiftTable; - } - } - else - { - result.Append(str); - // Go back to whatever mode we had been in - shiftTable = latchTable; - strTable = codeTables[shiftTable]; - } - } - } - return result.ToString(); - } - - /// - /// gets the table corresponding to the char passed - /// - /// The t. - /// - private static Table getTable(char t) - { - if (!codeTableMap.ContainsKey(t)) - return codeTableMap['U']; - return codeTableMap[t]; - } - - /// - /// Gets the character (or string) corresponding to the passed code in the given table - /// - /// the table used - /// the code of the character - /// - private static String getCharacter(String[] table, int code) - { - return table[code]; - } - - /// - ///Performs RS error correction on an array of bits. - /// - /// The rawbits. - /// the corrected array - private bool[] correctBits(bool[] rawbits) - { - GenericGF gf; - int codewordSize; - - if (ddata.NbLayers <= 2) - { - codewordSize = 6; - gf = GenericGF.AZTEC_DATA_6; - } - else if (ddata.NbLayers <= 8) - { - codewordSize = 8; - gf = GenericGF.AZTEC_DATA_8; - } - else if (ddata.NbLayers <= 22) - { - codewordSize = 10; - gf = GenericGF.AZTEC_DATA_10; - } - else - { - codewordSize = 12; - gf = GenericGF.AZTEC_DATA_12; - } - - int numDataCodewords = ddata.NbDatablocks; - int numCodewords = rawbits.Length/codewordSize; - if (numCodewords < numDataCodewords) - return null; - - int offset = rawbits.Length % codewordSize; - int numECCodewords = numCodewords - numDataCodewords; - - int[] dataWords = new int[numCodewords]; - for (int i = 0; i < numCodewords; i++, offset += codewordSize) - { - dataWords[i] = readCode(rawbits, offset, codewordSize); - } - - var rsDecoder = new ReedSolomonDecoder(gf); - if (!rsDecoder.decode(dataWords, numECCodewords)) - return null; - - // Now perform the unstuffing operation. - // First, count how many bits are going to be thrown out as stuffing - int mask = (1 << codewordSize) - 1; - int stuffedBits = 0; - for (int i = 0; i < numDataCodewords; i++) - { - int dataWord = dataWords[i]; - if (dataWord == 0 || dataWord == mask) - { - return null; - } - else if (dataWord == 1 || dataWord == mask - 1) - { - stuffedBits++; - } - } - // Now, actually unpack the bits and remove the stuffing - bool[] correctedBits = new bool[numDataCodewords*codewordSize - stuffedBits]; - int index = 0; - for (int i = 0; i < numDataCodewords; i++) - { - int dataWord = dataWords[i]; - if (dataWord == 1 || dataWord == mask - 1) - { - // next codewordSize-1 bits are all zeros or all ones - SupportClass.Fill(correctedBits, index, index + codewordSize - 1, dataWord > 1); - index += codewordSize - 1; - } - else - { - for (int bit = codewordSize - 1; bit >= 0; --bit) - { - correctedBits[index++] = (dataWord & (1 << bit)) != 0; - } - } - } - - if (index != correctedBits.Length) - return null; - - return correctedBits; - } - - /// - /// Gets the array of bits from an Aztec Code matrix - /// - /// The matrix. - /// the array of bits - private bool[] extractBits(BitMatrix matrix) - { - bool compact = ddata.Compact; - int layers = ddata.NbLayers; - int baseMatrixSize = compact ? 11 + layers*4 : 14 + layers*4; // not including alignment lines - int[] alignmentMap = new int[baseMatrixSize]; - bool[] rawbits = new bool[totalBitsInLayer(layers, compact)]; - - if (compact) - { - for (int i = 0; i < alignmentMap.Length; i++) - { - alignmentMap[i] = i; - } - } - else - { - int matrixSize = baseMatrixSize + 1 + 2*((baseMatrixSize/2 - 1)/15); - int origCenter = baseMatrixSize/2; - int center = matrixSize/2; - for (int i = 0; i < origCenter; i++) - { - int newOffset = i + i/15; - alignmentMap[origCenter - i - 1] = center - newOffset - 1; - alignmentMap[origCenter + i] = center + newOffset + 1; - } - } - for (int i = 0, rowOffset = 0; i < layers; i++) - { - int rowSize = compact ? (layers - i)*4 + 9 : (layers - i)*4 + 12; - // The top-left most point of this layer is (not including alignment lines) - int low = i*2; - // The bottom-right most point of this layer is (not including alignment lines) - int high = baseMatrixSize - 1 - low; - // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows - for (int j = 0; j < rowSize; j++) - { - int columnOffset = j*2; - for (int k = 0; k < 2; k++) - { - // left column - rawbits[rowOffset + columnOffset + k] = - matrix[alignmentMap[low + k], alignmentMap[low + j]]; - // bottom row - rawbits[rowOffset + 2*rowSize + columnOffset + k] = - matrix[alignmentMap[low + j], alignmentMap[high - k]]; - // right column - rawbits[rowOffset + 4*rowSize + columnOffset + k] = - matrix[alignmentMap[high - k], alignmentMap[high - j]]; - // top row - rawbits[rowOffset + 6*rowSize + columnOffset + k] = - matrix[alignmentMap[high - j], alignmentMap[low + k]]; - } - } - rowOffset += rowSize*8; - } - return rawbits; - } - - /// - /// Reads a code of given length and at given index in an array of bits - /// - /// The rawbits. - /// The start index. - /// The length. - /// - private static int readCode(bool[] rawbits, int startIndex, int length) - { - int res = 0; - for (int i = startIndex; i < startIndex + length; i++) - { - res <<= 1; - if (rawbits[i]) - { - res++; - } - } - return res; - } - - private static int totalBitsInLayer(int layers, bool compact) - { - return ((compact ? 88 : 112) + 16*layers)*layers; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/detector/Detector.cs b/zxing.core/xx/aztec/detector/Detector.cs deleted file mode 100644 index 3bb37f7..0000000 --- a/zxing.core/xx/aztec/detector/Detector.cs +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -using ZXing.Common; -using ZXing.Common.Detector; -using ZXing.Common.ReedSolomon; - -namespace ZXing.Aztec.Internal -{ - /// - /// Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code - /// is rotated or skewed, or partially obscured. - /// - /// David Olivier - public sealed class Detector - { - private readonly BitMatrix image; - - private bool compact; - private int nbLayers; - private int nbDataBlocks; - private int nbCenterLayers; - private int shift; - - /// - /// Initializes a new instance of the class. - /// - /// The image. - public Detector(BitMatrix image) - { - this.image = image; - } - - /// - /// Detects an Aztec Code in an image. - /// - public AztecDetectorResult detect() - { - return detect(false); - } - - /// - /// Detects an Aztec Code in an image. - /// - /// if true, image is a mirror-image of original. - /// - /// encapsulating results of detecting an Aztec Code - /// - public AztecDetectorResult detect(bool isMirror) - { - // 1. Get the center of the aztec matrix - var pCenter = getMatrixCenter(); - if (pCenter == null) - return null; - - // 2. Get the center points of the four diagonal points just outside the bull's eye - // [topRight, bottomRight, bottomLeft, topLeft] - var bullsEyeCorners = getBullsEyeCorners(pCenter); - if (bullsEyeCorners == null) - { - return null; - } - if (isMirror) - { - ResultPoint temp = bullsEyeCorners[0]; - bullsEyeCorners[0] = bullsEyeCorners[2]; - bullsEyeCorners[2] = temp; - } - - // 3. Get the size of the matrix and other parameters from the bull's eye - if (!extractParameters(bullsEyeCorners)) - { - return null; - } - - // 4. Sample the grid - var bits = sampleGrid(image, - bullsEyeCorners[shift%4], - bullsEyeCorners[(shift + 1)%4], - bullsEyeCorners[(shift + 2)%4], - bullsEyeCorners[(shift + 3)%4]); - if (bits == null) - { - return null; - } - - // 5. Get the corners of the matrix. - var corners = getMatrixCornerPoints(bullsEyeCorners); - if (corners == null) - { - return null; - } - - return new AztecDetectorResult(bits, corners, compact, nbDataBlocks, nbLayers); - } - - /// - /// Extracts the number of data layers and data blocks from the layer around the bull's eye - /// - /// bullEyeCornerPoints the array of bull's eye corners - /// - private bool extractParameters(ResultPoint[] bullsEyeCorners) - { - if (!isValid(bullsEyeCorners[0]) || !isValid(bullsEyeCorners[1]) || - !isValid(bullsEyeCorners[2]) || !isValid(bullsEyeCorners[3])) - { - return false; - } - - int length = 2 * nbCenterLayers; - - // Get the bits around the bull's eye - int[] sides = - { - sampleLine(bullsEyeCorners[0], bullsEyeCorners[1], length), // Right side - sampleLine(bullsEyeCorners[1], bullsEyeCorners[2], length), // Bottom - sampleLine(bullsEyeCorners[2], bullsEyeCorners[3], length), // Left side - sampleLine(bullsEyeCorners[3], bullsEyeCorners[0], length) // Top - }; - - - // bullsEyeCorners[shift] is the corner of the bulls'eye that has three - // orientation marks. - // sides[shift] is the row/column that goes from the corner with three - // orientation marks to the corner with two. - shift = getRotation(sides, length); - if (shift < 0) - return false; - - // Flatten the parameter bits into a single 28- or 40-bit long - long parameterData = 0; - for (int i = 0; i < 4; i++) - { - int side = sides[(shift + i) % 4]; - if (compact) - { - // Each side of the form ..XXXXXXX. where Xs are parameter data - parameterData <<= 7; - parameterData += (side >> 1) & 0x7F; - } - else - { - // Each side of the form ..XXXXX.XXXXX. where Xs are parameter data - parameterData <<= 10; - parameterData += ((side >> 2) & (0x1f << 5)) + ((side >> 1) & 0x1F); - } - } - - // Corrects parameter data using RS. Returns just the data portion - // without the error correction. - int correctedData = getCorrectedParameterData(parameterData, compact); - if (correctedData < 0) - return false; - - if (compact) - { - // 8 bits: 2 bits layers and 6 bits data blocks - nbLayers = (correctedData >> 6) + 1; - nbDataBlocks = (correctedData & 0x3F) + 1; - } - else - { - // 16 bits: 5 bits layers and 11 bits data blocks - nbLayers = (correctedData >> 11) + 1; - nbDataBlocks = (correctedData & 0x7FF) + 1; - } - - return true; - } - - private static readonly int[] EXPECTED_CORNER_BITS = - { - 0xee0, // 07340 XXX .XX X.. ... - 0x1dc, // 00734 ... XXX .XX X.. - 0x83b, // 04073 X.. ... XXX .XX - 0x707, // 03407 .XX X.. ... XXX - }; - - private static int getRotation(int[] sides, int length) - { - // In a normal pattern, we expect to See - // ** .* D A - // * * - // - // . * - // .. .. C B - // - // Grab the 3 bits from each of the sides the form the locator pattern and concatenate - // into a 12-bit integer. Start with the bit at A - int cornerBits = 0; - foreach (int side in sides) - { - // XX......X where X's are orientation marks - int t = ((side >> (length - 2)) << 1) + (side & 1); - cornerBits = (cornerBits << 3) + t; - } - // Mov the bottom bit to the top, so that the three bits of the locator pattern at A are - // together. cornerBits is now: - // 3 orientation bits at A || 3 orientation bits at B || ... || 3 orientation bits at D - cornerBits = ((cornerBits & 1) << 11) + (cornerBits >> 1); - // The result shift indicates which element of BullsEyeCorners[] goes into the top-left - // corner. Since the four rotation values have a Hamming distance of 8, we - // can easily tolerate two errors. - for (int shift = 0; shift < 4; shift++) - { - if (SupportClass.bitCount(cornerBits ^ EXPECTED_CORNER_BITS[shift]) <= 2) - { - return shift; - } - } - return -1; - } - - /// - /// Corrects the parameter bits using Reed-Solomon algorithm - /// - /// paremeter bits - /// compact true if this is a compact Aztec code - /// - private static int getCorrectedParameterData(long parameterData, bool compact) - { - int numCodewords; - int numDataCodewords; - - if (compact) - { - numCodewords = 7; - numDataCodewords = 2; - } - else - { - numCodewords = 10; - numDataCodewords = 4; - } - - int numECCodewords = numCodewords - numDataCodewords; - int[] parameterWords = new int[numCodewords]; - - for (int i = numCodewords - 1; i >= 0; --i) - { - parameterWords[i] = (int)parameterData & 0xF; - parameterData >>= 4; - } - - var rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM); - if (!rsDecoder.decode(parameterWords, numECCodewords)) - return -1; - - // Toss the error correction. Just return the data as an integer - int result = 0; - for (int i = 0; i < numDataCodewords; i++) - { - result = (result << 4) + parameterWords[i]; - } - return result; - } - - /// - /// Finds the corners of a bull-eye centered on the passed point - /// This returns the centers of the diagonal points just outside the bull's eye - /// Returns [topRight, bottomRight, bottomLeft, topLeft] - /// - /// Center point - /// The corners of the bull-eye - private ResultPoint[] getBullsEyeCorners(Point pCenter) - { - Point pina = pCenter; - Point pinb = pCenter; - Point pinc = pCenter; - Point pind = pCenter; - - bool color = true; - - for (nbCenterLayers = 1; nbCenterLayers < 9; nbCenterLayers++) - { - Point pouta = getFirstDifferent(pina, color, 1, -1); - Point poutb = getFirstDifferent(pinb, color, 1, 1); - Point poutc = getFirstDifferent(pinc, color, -1, 1); - Point poutd = getFirstDifferent(pind, color, -1, -1); - - //d a - // - //c b - - if (nbCenterLayers > 2) - { - float q = distance(poutd, pouta)*nbCenterLayers/(distance(pind, pina)*(nbCenterLayers + 2)); - if (q < 0.75 || q > 1.25 || !isWhiteOrBlackRectangle(pouta, poutb, poutc, poutd)) - { - break; - } - } - - pina = pouta; - pinb = poutb; - pinc = poutc; - pind = poutd; - - color = !color; - } - - if (nbCenterLayers != 5 && nbCenterLayers != 7) - { - return null; - } - - compact = nbCenterLayers == 5; - - // Expand the square by .5 pixel in each direction so that we're on the border - // between the white square and the black square - var pinax = new ResultPoint(pina.X + 0.5f, pina.Y - 0.5f); - var pinbx = new ResultPoint(pinb.X + 0.5f, pinb.Y + 0.5f); - var pincx = new ResultPoint(pinc.X - 0.5f, pinc.Y + 0.5f); - var pindx = new ResultPoint(pind.X - 0.5f, pind.Y - 0.5f); - - // Expand the square so that its corners are the centers of the points - // just outside the bull's eye. - return expandSquare(new[] {pinax, pinbx, pincx, pindx}, - 2*nbCenterLayers - 3, - 2*nbCenterLayers); - } - - /// - /// Finds a candidate center point of an Aztec code from an image - /// - /// the center point - private Point getMatrixCenter() - { - ResultPoint pointA; - ResultPoint pointB; - ResultPoint pointC; - ResultPoint pointD; - int cx; - int cy; - - //Get a white rectangle that can be the border of the matrix in center bull's eye or - var whiteDetector = WhiteRectangleDetector.Create(image); - if (whiteDetector == null) - return null; - ResultPoint[] cornerPoints = whiteDetector.detect(); - if (cornerPoints != null) - { - pointA = cornerPoints[0]; - pointB = cornerPoints[1]; - pointC = cornerPoints[2]; - pointD = cornerPoints[3]; - } - else - { - - // This exception can be in case the initial rectangle is white - // In that case, surely in the bull's eye, we try to expand the rectangle. - cx = image.Width/2; - cy = image.Height/2; - pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); - pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); - pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); - pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); - } - - //Compute the center of the rectangle - cx = MathUtils.round((pointA.X + pointD.X + pointB.X + pointC.X) / 4.0f); - cy = MathUtils.round((pointA.Y + pointD.Y + pointB.Y + pointC.Y) / 4.0f); - - // Redetermine the white rectangle starting from previously computed center. - // This will ensure that we end up with a white rectangle in center bull's eye - // in order to compute a more accurate center. - whiteDetector = WhiteRectangleDetector.Create(image, 15, cx, cy); - if (whiteDetector == null) - return null; - cornerPoints = whiteDetector.detect(); - if (cornerPoints != null) - { - pointA = cornerPoints[0]; - pointB = cornerPoints[1]; - pointC = cornerPoints[2]; - pointD = cornerPoints[3]; - } - else - { - // This exception can be in case the initial rectangle is white - // In that case we try to expand the rectangle. - pointA = getFirstDifferent(new Point(cx + 7, cy - 7), false, 1, -1).toResultPoint(); - pointB = getFirstDifferent(new Point(cx + 7, cy + 7), false, 1, 1).toResultPoint(); - pointC = getFirstDifferent(new Point(cx - 7, cy + 7), false, -1, 1).toResultPoint(); - pointD = getFirstDifferent(new Point(cx - 7, cy - 7), false, -1, -1).toResultPoint(); - } - - // Recompute the center of the rectangle - cx = MathUtils.round((pointA.X + pointD.X + pointB.X + pointC.X) / 4.0f); - cy = MathUtils.round((pointA.Y + pointD.Y + pointB.Y + pointC.Y) / 4.0f); - - return new Point(cx, cy); - } - - /// - /// Gets the Aztec code corners from the bull's eye corners and the parameters. - /// - /// the array of bull's eye corners - /// the array of aztec code corners - private ResultPoint[] getMatrixCornerPoints(ResultPoint[] bullsEyeCorners) - { - return expandSquare(bullsEyeCorners, 2 * nbCenterLayers, getDimension()); - } - - /// - /// Creates a BitMatrix by sampling the provided image. - /// topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the - /// diagonal just outside the bull's eye. - /// - /// The image. - /// The top left. - /// The bottom left. - /// The bottom right. - /// The top right. - /// - private BitMatrix sampleGrid(BitMatrix image, - ResultPoint topLeft, - ResultPoint topRight, - ResultPoint bottomRight, - ResultPoint bottomLeft) - { - GridSampler sampler = GridSampler.Instance; - int dimension = getDimension(); - - float low = dimension/2.0f - nbCenterLayers; - float high = dimension/2.0f + nbCenterLayers; - - return sampler.sampleGrid(image, - dimension, - dimension, - low, low, // topleft - high, low, // topright - high, high, // bottomright - low, high, // bottomleft - topLeft.X, topLeft.Y, - topRight.X, topRight.Y, - bottomRight.X, bottomRight.Y, - bottomLeft.X, bottomLeft.Y); - } - - /// - /// Samples a line - /// - /// start point (inclusive) - /// end point (exclusive) - /// number of bits - /// the array of bits as an int (first bit is high-order bit of result) - private int sampleLine(ResultPoint p1, ResultPoint p2, int size) - { - int result = 0; - - float d = distance(p1, p2); - float moduleSize = d / size; - float px = p1.X; - float py = p1.Y; - float dx = moduleSize * (p2.X - p1.X) / d; - float dy = moduleSize * (p2.Y - p1.Y) / d; - for (int i = 0; i < size; i++) - { - if (image[MathUtils.round(px + i * dx), MathUtils.round(py + i * dy)]) - { - result |= 1 << (size - i - 1); - } - } - return result; - } - - /// - /// Determines whether [is white or black rectangle] [the specified p1]. - /// - /// The p1. - /// The p2. - /// The p3. - /// The p4. - /// true if the border of the rectangle passed in parameter is compound of white points only - /// or black points only - private bool isWhiteOrBlackRectangle(Point p1, Point p2, Point p3, Point p4) - { - const int corr = 3; - - p1 = new Point(p1.X - corr, p1.Y + corr); - p2 = new Point(p2.X - corr, p2.Y - corr); - p3 = new Point(p3.X + corr, p3.Y - corr); - p4 = new Point(p4.X + corr, p4.Y + corr); - - int cInit = getColor(p4, p1); - - if (cInit == 0) - { - return false; - } - - int c = getColor(p1, p2); - - if (c != cInit) - { - return false; - } - - c = getColor(p2, p3); - - if (c != cInit) - { - return false; - } - - c = getColor(p3, p4); - - return c == cInit; - - } - - /// - /// Gets the color of a segment - /// - /// The p1. - /// The p2. - /// 1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else - private int getColor(Point p1, Point p2) - { - float d = distance(p1, p2); - float dx = (p2.X - p1.X) / d; - float dy = (p2.Y - p1.Y) / d; - int error = 0; - - float px = p1.X; - float py = p1.Y; - - bool colorModel = image[p1.X, p1.Y]; - - for (int i = 0; i < d; i++) - { - px += dx; - py += dy; - if (image[MathUtils.round(px), MathUtils.round(py)] != colorModel) - { - error++; - } - } - - float errRatio = error / d; - - if (errRatio > 0.1f && errRatio < 0.9f) - { - return 0; - } - - return (errRatio <= 0.1f) == colorModel ? 1 : -1; - } - - /// - /// Gets the coordinate of the first point with a different color in the given direction - /// - /// The init. - /// if set to true [color]. - /// The dx. - /// The dy. - /// - private Point getFirstDifferent(Point init, bool color, int dx, int dy) - { - int x = init.X + dx; - int y = init.Y + dy; - - while (isValid(x, y) && image[x, y] == color) - { - x += dx; - y += dy; - } - - x -= dx; - y -= dy; - - while (isValid(x, y) && image[x, y] == color) - { - x += dx; - } - x -= dx; - - while (isValid(x, y) && image[x, y] == color) - { - y += dy; - } - y -= dy; - - return new Point(x, y); - } - - /// - /// Expand the square represented by the corner points by pushing out equally in all directions - /// - /// the corners of the square, which has the bull's eye at its center - /// the original length of the side of the square in the target bit matrix - /// the new length of the size of the square in the target bit matrix - /// the corners of the expanded square - private static ResultPoint[] expandSquare(ResultPoint[] cornerPoints, float oldSide, float newSide) - { - float ratio = newSide/(2*oldSide); - float dx = cornerPoints[0].X - cornerPoints[2].X; - float dy = cornerPoints[0].Y - cornerPoints[2].Y; - float centerx = (cornerPoints[0].X + cornerPoints[2].X)/2.0f; - float centery = (cornerPoints[0].Y + cornerPoints[2].Y)/2.0f; - - var result0 = new ResultPoint(centerx + ratio*dx, centery + ratio*dy); - var result2 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); - - dx = cornerPoints[1].X - cornerPoints[3].X; - dy = cornerPoints[1].Y - cornerPoints[3].Y; - centerx = (cornerPoints[1].X + cornerPoints[3].X)/2.0f; - centery = (cornerPoints[1].Y + cornerPoints[3].Y)/2.0f; - var result1 = new ResultPoint(centerx + ratio * dx, centery + ratio * dy); - var result3 = new ResultPoint(centerx - ratio * dx, centery - ratio * dy); - - return new ResultPoint[] {result0, result1, result2, result3}; - } - - private bool isValid(int x, int y) - { - return x >= 0 && x < image.Width && y > 0 && y < image.Height; - } - - private bool isValid(ResultPoint point) - { - int x = MathUtils.round(point.X); - int y = MathUtils.round(point.Y); - return isValid(x, y); - } - - // L2 distance - private static float distance(Point a, Point b) - { - return MathUtils.distance(a.X, a.Y, b.X, b.Y); - } - - private static float distance(ResultPoint a, ResultPoint b) - { - return MathUtils.distance(a.X, a.Y, b.X, b.Y); - } - - private int getDimension() - { - if (compact) - { - return 4 * nbLayers + 11; - } - if (nbLayers <= 4) - { - return 4 * nbLayers + 15; - } - return 4 * nbLayers + 2 * ((nbLayers - 4) / 8 + 1) + 15; - } - - internal sealed class Point - { - public int X { get; private set; } - public int Y { get; private set; } - - public ResultPoint toResultPoint() - { - return new ResultPoint(X, Y); - } - - internal Point(int x, int y) - { - X = x; - Y = y; - } - - public override String ToString() - { - return "<" + X + ' ' + Y + '>'; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/encoder/AztecCode.cs b/zxing.core/xx/aztec/encoder/AztecCode.cs deleted file mode 100644 index 137b8b7..0000000 --- a/zxing.core/xx/aztec/encoder/AztecCode.cs +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013 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 ZXing.Common; - -namespace ZXing.Aztec.Internal -{ - /// - /// Aztec 2D code representation - /// - /// Rustam Abdullaev - public sealed class AztecCode - { - /// - /// Compact or full symbol indicator - /// - public bool isCompact { get; set; } - - /// - /// Size in pixels (width and height) - /// - public int Size { get; set; } - - /// - /// Number of levels - /// - public int Layers { get; set; } - - /// - /// Number of data codewords - /// - public int CodeWords { get; set; } - - /// - /// The symbol image - /// - public BitMatrix Matrix { get; set; } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/encoder/AztecEncodingOptions.cs b/zxing.core/xx/aztec/encoder/AztecEncodingOptions.cs deleted file mode 100644 index c636c4b..0000000 --- a/zxing.core/xx/aztec/encoder/AztecEncodingOptions.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 ZXing.Common; - -namespace ZXing.Aztec -{ - /// - /// The class holds the available options for the - /// - public class AztecEncodingOptions : EncodingOptions - { - /// - /// Representing the minimal percentage of error correction words. - /// Note: an Aztec symbol should have a minimum of 25% EC words. - /// - public int? ErrorCorrection - { - get - { - if (Hints.ContainsKey(EncodeHintType.ERROR_CORRECTION)) - { - return (int)Hints[EncodeHintType.ERROR_CORRECTION]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.ERROR_CORRECTION)) - Hints.Remove(EncodeHintType.ERROR_CORRECTION); - } - else - { - Hints[EncodeHintType.ERROR_CORRECTION] = value; - } - } - } - - /// - /// Specifies the required number of layers for an Aztec code: - /// a negative number (-1, -2, -3, -4) specifies a compact Aztec code - /// 0 indicates to use the minimum number of layers (the default) - /// a positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code - /// - public int? Layers - { - get - { - if (Hints.ContainsKey(EncodeHintType.AZTEC_LAYERS)) - { - return (int)Hints[EncodeHintType.AZTEC_LAYERS]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.AZTEC_LAYERS)) - Hints.Remove(EncodeHintType.AZTEC_LAYERS); - } - else - { - Hints[EncodeHintType.AZTEC_LAYERS] = value; - } - } - } - } -} diff --git a/zxing.core/xx/aztec/encoder/BinaryShiftToken.cs b/zxing.core/xx/aztec/encoder/BinaryShiftToken.cs deleted file mode 100644 index cc3fd0a..0000000 --- a/zxing.core/xx/aztec/encoder/BinaryShiftToken.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -using ZXing.Common; - -namespace ZXing.Aztec.Internal -{ - public sealed class BinaryShiftToken : Token - { - private readonly short binaryShiftStart; - private readonly short binaryShiftByteCount; - - public BinaryShiftToken(Token previous, - int binaryShiftStart, - int binaryShiftByteCount) - : base(previous) - { - this.binaryShiftStart = (short) binaryShiftStart; - this.binaryShiftByteCount = (short) binaryShiftByteCount; - } - - public override void appendTo(BitArray bitArray, byte[] text) - { - for (int i = 0; i < binaryShiftByteCount; i++) - { - if (i == 0 || (i == 31 && binaryShiftByteCount <= 62)) - { - // We need a header before the first character, and before - // character 31 when the total byte code is <= 62 - bitArray.appendBits(31, 5); // BINARY_SHIFT - if (binaryShiftByteCount > 62) - { - bitArray.appendBits(binaryShiftByteCount - 31, 16); - } - else if (i == 0) - { - // 1 <= binaryShiftByteCode <= 62 - bitArray.appendBits(Math.Min(binaryShiftByteCount, (short) 31), 5); - } - else - { - // 32 <= binaryShiftCount <= 62 and i == 31 - bitArray.appendBits(binaryShiftByteCount - 31, 5); - } - } - bitArray.appendBits(text[binaryShiftStart + i], 8); - } - } - - public override String ToString() - { - return "<" + binaryShiftStart + "::" + (binaryShiftStart + binaryShiftByteCount - 1) + '>'; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/encoder/Encoder.cs b/zxing.core/xx/aztec/encoder/Encoder.cs deleted file mode 100644 index cf4fb99..0000000 --- a/zxing.core/xx/aztec/encoder/Encoder.cs +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -using ZXing.Common; -using ZXing.Common.ReedSolomon; - -namespace ZXing.Aztec.Internal -{ - /// - /// Generates Aztec 2D barcodes. - /// - /// Rustam Abdullaev - public static class Encoder - { - public const int DEFAULT_EC_PERCENT = 33; // default minimal percentage of error check words - public const int DEFAULT_AZTEC_LAYERS = 0; - private const int MAX_NB_BITS = 32; - private const int MAX_NB_BITS_COMPACT = 4; - - private static readonly int[] WORD_SIZE = { - 4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 - }; - - /// - /// Encodes the given binary content as an Aztec symbol - /// - /// input data string - /// Aztec symbol matrix with metadata - - public static AztecCode encode(byte[] data) - { - return encode(data, DEFAULT_EC_PERCENT, DEFAULT_AZTEC_LAYERS); - } - - /// - /// Encodes the given binary content as an Aztec symbol - /// - /// input data string - /// minimal percentage of error check words (According to ISO/IEC 24778:2008, - /// a minimum of 23% + 3 words is recommended) - /// if non-zero, a user-specified value for the number of layers - /// - /// Aztec symbol matrix with metadata - /// - public static AztecCode encode(byte[] data, int minECCPercent, int userSpecifiedLayers) - { - // High-level encode - var bits = new HighLevelEncoder(data).encode(); - - // stuff bits and choose symbol size - int eccBits = bits.Size*minECCPercent/100 + 11; - int totalSizeBits = bits.Size + eccBits; - bool compact; - int layers; - int totalBitsInLayer; - int wordSize; - BitArray stuffedBits; - - if (userSpecifiedLayers != DEFAULT_AZTEC_LAYERS) - { - compact = userSpecifiedLayers < 0; - layers = Math.Abs(userSpecifiedLayers); - if (layers > (compact ? MAX_NB_BITS_COMPACT : MAX_NB_BITS)) - { - throw new ArgumentException( - String.Format("Illegal value {0} for layers", userSpecifiedLayers)); - } - totalBitsInLayer = TotalBitsInLayer(layers, compact); - wordSize = WORD_SIZE[layers]; - int usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer%wordSize); - stuffedBits = stuffBits(bits, wordSize); - if (stuffedBits.Size + eccBits > usableBitsInLayers) - { - throw new ArgumentException("Data to large for user specified layer"); - } - if (compact && stuffedBits.Size > wordSize*64) - { - // Compact format only allows 64 data words, though C4 can hold more words than that - throw new ArgumentException("Data to large for user specified layer"); - } - } - else - { - wordSize = 0; - stuffedBits = null; - // We look at the possible table sizes in the order Compact1, Compact2, Compact3, - // Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1) - // is the same size, but has more data. - for (int i = 0;; i++) - { - if (i > MAX_NB_BITS) - { - throw new ArgumentException("Data too large for an Aztec code"); - } - compact = i <= 3; - layers = compact ? i + 1 : i; - totalBitsInLayer = TotalBitsInLayer(layers, compact); - if (totalSizeBits > totalBitsInLayer) - { - continue; - } - // [Re]stuff the bits if this is the first opportunity, or if the - // wordSize has changed - if (wordSize != WORD_SIZE[layers]) - { - wordSize = WORD_SIZE[layers]; - stuffedBits = stuffBits(bits, wordSize); - } - if (stuffedBits == null) - { - continue; - } - int usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer%wordSize); - if (compact && stuffedBits.Size > wordSize*64) - { - // Compact format only allows 64 data words, though C4 can hold more words than that - continue; - } - if (stuffedBits.Size + eccBits <= usableBitsInLayers) - { - break; - } - } - - } - - BitArray messageBits = generateCheckWords(stuffedBits, totalBitsInLayer, wordSize); - - // generate mode message - int messageSizeInWords = stuffedBits.Size / wordSize; - var modeMessage = generateModeMessage(compact, layers, messageSizeInWords); - - // allocate symbol - var baseMatrixSize = compact ? 11 + layers*4 : 14 + layers*4; // not including alignment lines - var alignmentMap = new int[baseMatrixSize]; - int matrixSize; - if (compact) - { - // no alignment marks in compact mode, alignmentMap is a no-op - matrixSize = baseMatrixSize; - for (int i = 0; i < alignmentMap.Length; i++) - { - alignmentMap[i] = i; - } - } - else - { - matrixSize = baseMatrixSize + 1 + 2*((baseMatrixSize/2 - 1)/15); - int origCenter = baseMatrixSize/2; - int center = matrixSize/2; - for (int i = 0; i < origCenter; i++) - { - int newOffset = i + i/15; - alignmentMap[origCenter - i - 1] = center - newOffset - 1; - alignmentMap[origCenter + i] = center + newOffset + 1; - } - } - var matrix = new BitMatrix(matrixSize); - - // draw data bits - for (int i = 0, rowOffset = 0; i < layers; i++) - { - int rowSize = compact ? (layers - i)*4 + 9 : (layers - i)*4 + 12; - for (int j = 0; j < rowSize; j++) - { - int columnOffset = j*2; - for (int k = 0; k < 2; k++) - { - if (messageBits[rowOffset + columnOffset + k]) - { - matrix[alignmentMap[i*2 + k], alignmentMap[i*2 + j]] = true; - } - if (messageBits[rowOffset + rowSize*2 + columnOffset + k]) - { - matrix[alignmentMap[i*2 + j], alignmentMap[baseMatrixSize - 1 - i*2 - k]] = true; - } - if (messageBits[rowOffset + rowSize*4 + columnOffset + k]) - { - matrix[alignmentMap[baseMatrixSize - 1 - i*2 - k], alignmentMap[baseMatrixSize - 1 - i*2 - j]] = true; - } - if (messageBits[rowOffset + rowSize*6 + columnOffset + k]) - { - matrix[alignmentMap[baseMatrixSize - 1 - i*2 - j], alignmentMap[i*2 + k]] = true; - } - } - } - rowOffset += rowSize*8; - } - - // draw mode message - drawModeMessage(matrix, compact, matrixSize, modeMessage); - - // draw alignment marks - if (compact) - { - drawBullsEye(matrix, matrixSize/2, 5); - } - else - { - drawBullsEye(matrix, matrixSize/2, 7); - for (int i = 0, j = 0; i < baseMatrixSize/2 - 1; i += 15, j += 16) - { - for (int k = (matrixSize/2) & 1; k < matrixSize; k += 2) - { - matrix[matrixSize/2 - j, k] = true; - matrix[matrixSize/2 + j, k] = true; - matrix[k, matrixSize/2 - j] = true; - matrix[k, matrixSize/2 + j] = true; - } - } - } - - return new AztecCode - { - isCompact = compact, - Size = matrixSize, - Layers = layers, - CodeWords = messageSizeInWords, - Matrix = matrix - }; - } - - private static void drawBullsEye(BitMatrix matrix, int center, int size) - { - for (var i = 0; i < size; i += 2) - { - for (var j = center - i; j <= center + i; j++) - { - matrix[j, center - i] = true; - matrix[j, center + i] = true; - matrix[center - i, j] = true; - matrix[center + i, j] = true; - } - } - matrix[center - size, center - size] = true; - matrix[center - size + 1, center - size] = true; - matrix[center - size, center - size + 1] = true; - matrix[center + size, center - size] = true; - matrix[center + size, center - size + 1] = true; - matrix[center + size, center + size - 1] = true; - } - - internal static BitArray generateModeMessage(bool compact, int layers, int messageSizeInWords) - { - var modeMessage = new BitArray(); - if (compact) - { - modeMessage.appendBits(layers - 1, 2); - modeMessage.appendBits(messageSizeInWords - 1, 6); - modeMessage = generateCheckWords(modeMessage, 28, 4); - } - else - { - modeMessage.appendBits(layers - 1, 5); - modeMessage.appendBits(messageSizeInWords - 1, 11); - modeMessage = generateCheckWords(modeMessage, 40, 4); - } - return modeMessage; - } - - private static void drawModeMessage(BitMatrix matrix, bool compact, int matrixSize, BitArray modeMessage) - { - int center = matrixSize / 2; - - if (compact) - { - for (var i = 0; i < 7; i++) - { - int offset = center - 3 + i; - if (modeMessage[i]) - { - matrix[offset, center - 5] = true; - } - if (modeMessage[i + 7]) - { - matrix[center + 5, offset] = true; - } - if (modeMessage[20 - i]) - { - matrix[offset, center + 5] = true; - } - if (modeMessage[27 - i]) - { - matrix[center - 5, offset] = true; - } - } - } - else - { - for (var i = 0; i < 10; i++) - { - int offset = center - 5 + i + i / 5; - if (modeMessage[i]) - { - matrix[offset, center - 7] = true; - } - if (modeMessage[i + 10]) - { - matrix[center + 7, offset] = true; - } - if (modeMessage[29 - i]) - { - matrix[offset, center + 7] = true; - } - if (modeMessage[39 - i]) - { - matrix[center - 7, offset] = true; - } - } - } - } - - private static BitArray generateCheckWords(BitArray bitArray, int totalBits, int wordSize) - { - if (bitArray.Size % wordSize != 0) - throw new InvalidOperationException("size of bit array is not a multiple of the word size"); - - // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed - int messageSizeInWords = bitArray.Size / wordSize; - - var rs = new ReedSolomonEncoder(getGF(wordSize)); - var totalWords = totalBits / wordSize; - var messageWords = bitsToWords(bitArray, wordSize, totalWords); - rs.encode(messageWords, totalWords - messageSizeInWords); - - var startPad = totalBits % wordSize; - var messageBits = new BitArray(); - messageBits.appendBits(0, startPad); - foreach (var messageWord in messageWords) - { - messageBits.appendBits(messageWord, wordSize); - } - return messageBits; - } - - private static int[] bitsToWords(BitArray stuffedBits, int wordSize, int totalWords) - { - var message = new int[totalWords]; - int i; - int n; - for (i = 0, n = stuffedBits.Size / wordSize; i < n; i++) - { - int value = 0; - for (int j = 0; j < wordSize; j++) - { - value |= stuffedBits[i * wordSize + j] ? (1 << wordSize - j - 1) : 0; - } - message[i] = value; - } - return message; - } - - private static GenericGF getGF(int wordSize) - { - switch (wordSize) - { - case 4: - return GenericGF.AZTEC_PARAM; - case 6: - return GenericGF.AZTEC_DATA_6; - case 8: - return GenericGF.AZTEC_DATA_8; - case 10: - return GenericGF.AZTEC_DATA_10; - case 12: - return GenericGF.AZTEC_DATA_12; - default: - return null; - } - } - - internal static BitArray stuffBits(BitArray bits, int wordSize) - { - var @out = new BitArray(); - - int n = bits.Size; - int mask = (1 << wordSize) - 2; - for (int i = 0; i < n; i += wordSize) - { - int word = 0; - for (int j = 0; j < wordSize; j++) - { - if (i + j >= n || bits[i + j]) - { - word |= 1 << (wordSize - 1 - j); - } - } - if ((word & mask) == mask) - { - @out.appendBits(word & mask, wordSize); - i--; - } - else if ((word & mask) == 0) - { - @out.appendBits(word | 1, wordSize); - i--; - } - else - { - @out.appendBits(word, wordSize); - } - } - - return @out; - } - - private static int TotalBitsInLayer(int layers, bool compact) - { - return ((compact ? 88 : 112) + 16 * layers) * layers; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/encoder/HighLevelEncoder.cs b/zxing.core/xx/aztec/encoder/HighLevelEncoder.cs deleted file mode 100644 index e8ce1b5..0000000 --- a/zxing.core/xx/aztec/encoder/HighLevelEncoder.cs +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2013 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.Collections.ObjectModel; - -using ZXing.Common; - -namespace ZXing.Aztec.Internal -{ - /// - /// This produces nearly optimal encodings of text into the first-level of - /// encoding used by Aztec code. - /// It uses a dynamic algorithm. For each prefix of the string, it determines - /// a set of encodings that could lead to this prefix. We repeatedly add a - /// character and generate a new set of optimal encodings until we have read - /// through the entire input. - /// @author Frank Yellin - /// @author Rustam Abdullaev - /// - public sealed class HighLevelEncoder - { - - internal static String[] MODE_NAMES = {"UPPER", "LOWER", "DIGIT", "MIXED", "PUNCT"}; - - internal const int MODE_UPPER = 0; // 5 bits - internal const int MODE_LOWER = 1; // 5 bits - internal const int MODE_DIGIT = 2; // 4 bits - internal const int MODE_MIXED = 3; // 5 bits - internal const int MODE_PUNCT = 4; // 5 bits - - // The Latch Table shows, for each pair of Modes, the optimal method for - // getting from one mode to another. In the worst possible case, this can - // be up to 14 bits. In the best possible case, we are already there! - // The high half-word of each entry gives the number of bits. - // The low half-word of each entry are the actual bits necessary to change - internal static readonly int[][] LATCH_TABLE = new int[][] - { - new[] - { - 0, - (5 << 16) + 28, // UPPER -> LOWER - (5 << 16) + 30, // UPPER -> DIGIT - (5 << 16) + 29, // UPPER -> MIXED - (10 << 16) + (29 << 5) + 30, // UPPER -> MIXED -> PUNCT - }, - new[] - { - (9 << 16) + (30 << 4) + 14, // LOWER -> DIGIT -> UPPER - 0, - (5 << 16) + 30, // LOWER -> DIGIT - (5 << 16) + 29, // LOWER -> MIXED - (10 << 16) + (29 << 5) + 30, // LOWER -> MIXED -> PUNCT - }, - new[] - { - (4 << 16) + 14, // DIGIT -> UPPER - (9 << 16) + (14 << 5) + 28, // DIGIT -> UPPER -> LOWER - 0, - (9 << 16) + (14 << 5) + 29, // DIGIT -> UPPER -> MIXED - (14 << 16) + (14 << 10) + (29 << 5) + 30, - // DIGIT -> UPPER -> MIXED -> PUNCT - }, - new[] - { - (5 << 16) + 29, // MIXED -> UPPER - (5 << 16) + 28, // MIXED -> LOWER - (10 << 16) + (29 << 5) + 30, // MIXED -> UPPER -> DIGIT - 0, - (5 << 16) + 30, // MIXED -> PUNCT - }, - new[] - { - (5 << 16) + 31, // PUNCT -> UPPER - (10 << 16) + (31 << 5) + 28, // PUNCT -> UPPER -> LOWER - (10 << 16) + (31 << 5) + 30, // PUNCT -> UPPER -> DIGIT - (10 << 16) + (31 << 5) + 29, // PUNCT -> UPPER -> MIXED - 0, - }, - }; - - // A reverse mapping from [mode][char] to the encoding for that character - // in that mode. An entry of 0 indicates no mapping exists. - internal static readonly int[][] CHAR_MAP = new int[5][]; - // A map showing the available shift codes. (The shifts to BINARY are not shown - internal static readonly int[][] SHIFT_TABLE = new int[6][]; // mode shift codes, per table - private readonly byte[] text; - - static HighLevelEncoder() - { - CHAR_MAP[0] = new int[256]; - CHAR_MAP[1] = new int[256]; - CHAR_MAP[2] = new int[256]; - CHAR_MAP[3] = new int[256]; - CHAR_MAP[4] = new int[256]; - - SHIFT_TABLE[0] = new int[6]; - SHIFT_TABLE[1] = new int[6]; - SHIFT_TABLE[2] = new int[6]; - SHIFT_TABLE[3] = new int[6]; - SHIFT_TABLE[4] = new int[6]; - SHIFT_TABLE[5] = new int[6]; - - CHAR_MAP[MODE_UPPER][' '] = 1; - for (int c = 'A'; c <= 'Z'; c++) - { - CHAR_MAP[MODE_UPPER][c] = c - 'A' + 2; - } - CHAR_MAP[MODE_LOWER][' '] = 1; - for (int c = 'a'; c <= 'z'; c++) - { - CHAR_MAP[MODE_LOWER][c] = c - 'a' + 2; - } - CHAR_MAP[MODE_DIGIT][' '] = 1; - for (int c = '0'; c <= '9'; c++) - { - CHAR_MAP[MODE_DIGIT][c] = c - '0' + 2; - } - CHAR_MAP[MODE_DIGIT][','] = 12; - CHAR_MAP[MODE_DIGIT]['.'] = 13; - int[] mixedTable = { - '\0', ' ', 1, 2, 3, 4, 5, 6, 7, '\b', '\t', '\n', 11, '\f', '\r', - 27, 28, 29, 30, 31, '@', '\\', '^', '_', '`', '|', '~', 127 - }; - for (int i = 0; i < mixedTable.Length; i++) - { - CHAR_MAP[MODE_MIXED][mixedTable[i]] = i; - } - int[] punctTable = - { - '\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', - '[', ']', '{', '}' - }; - for (int i = 0; i < punctTable.Length; i++) - { - if (punctTable[i] > 0) - { - CHAR_MAP[MODE_PUNCT][punctTable[i]] = i; - } - } - foreach (int[] table in SHIFT_TABLE) - { - SupportClass.Fill(table, -1); - } - SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0; - - SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0; - SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28; - - SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0; - - SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0; - SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15; - } - - public HighLevelEncoder(byte[] text) - { - this.text = text; - } - - /// - /// Convert the text represented by this High Level Encoder into a BitArray. - /// - /// text represented by this encoder encoded as a - public BitArray encode() - { - ICollection states = new Collection(); - states.Add(State.INITIAL_STATE); - for (int index = 0; index < text.Length; index++) - { - int pairCode; - // don't remove the (int) type cast, mono compiler needs it - int nextChar = (index + 1 < text.Length) ? (int)text[index + 1] : 0; - switch (text[index]) - { - case (byte)'\r': - pairCode = nextChar == '\n' ? 2 : 0; - break; - case (byte)'.': - pairCode = nextChar == ' ' ? 3 : 0; - break; - case (byte)',': - pairCode = nextChar == ' ' ? 4 : 0; - break; - case (byte)':': - pairCode = nextChar == ' ' ? 5 : 0; - break; - default: - pairCode = 0; - break; - } - if (pairCode > 0) - { - // We have one of the four special PUNCT pairs. Treat them specially. - // Get a new set of states for the two new characters. - states = updateStateListForPair(states, index, pairCode); - index++; - } - else - { - // Get a new set of states for the new character. - states = updateStateListForChar(states, index); - } - } - // We are left with a set of states. Find the shortest one. - State minState = null; - foreach (var state in states) - { - if (minState == null) - { - minState = state; - } - else - { - if (state.BitCount < minState.BitCount) - { - minState = state; - } - } - } - /* - State minState = Collections.min(states, new Comparator() { - @Override - public int compare(State a, State b) { - return a.getBitCount() - b.getBitCount(); - } - }); - */ - // Convert it to a bit array, and return. - return minState.toBitArray(text); - } - - // We update a set of states for a new character by updating each state - // for the new character, merging the results, and then removing the - // non-optimal states. - private ICollection updateStateListForChar(IEnumerable states, int index) - { - var result = new LinkedList(); - foreach (State state in states) - { - updateStateForChar(state, index, result); - } - return simplifyStates(result); - } - - // Return a set of states that represent the possible ways of updating this - // state for the next character. The resulting set of states are added to - // the "result" list. - private void updateStateForChar(State state, int index, ICollection result) - { - char ch = (char) (text[index] & 0xFF); - bool charInCurrentTable = CHAR_MAP[state.Mode][ch] > 0; - State stateNoBinary = null; - for (int mode = 0; mode <= MODE_PUNCT; mode++) - { - int charInMode = CHAR_MAP[mode][ch]; - if (charInMode > 0) - { - if (stateNoBinary == null) - { - // Only create stateNoBinary the first time it's required. - stateNoBinary = state.endBinaryShift(index); - } - // Try generating the character by latching to its mode - if (!charInCurrentTable || mode == state.Mode || mode == MODE_DIGIT) - { - // If the character is in the current table, we don't want to latch to - // any other mode except possibly digit (which uses only 4 bits). Any - // other latch would be equally successful *after* this character, and - // so wouldn't save any bits. - State latch_state = stateNoBinary.latchAndAppend(mode, charInMode); - result.Add(latch_state); - } - // Try generating the character by switching to its mode. - if (!charInCurrentTable && SHIFT_TABLE[state.Mode][mode] >= 0) - { - // It never makes sense to temporarily shift to another mode if the - // character exists in the current mode. That can never save bits. - State shift_state = stateNoBinary.shiftAndAppend(mode, charInMode); - result.Add(shift_state); - } - } - } - if (state.BinaryShiftByteCount > 0 || CHAR_MAP[state.Mode][ch] == 0) - { - // It's never worthwhile to go into binary shift mode if you're not already - // in binary shift mode, and the character exists in your current mode. - // That can never save bits over just outputting the char in the current mode. - State binaryState = state.addBinaryShiftChar(index); - result.Add(binaryState); - } - } - - private static ICollection updateStateListForPair(IEnumerable states, int index, int pairCode) - { - var result = new LinkedList(); - foreach (State state in states) - { - updateStateForPair(state, index, pairCode, result); - } - return simplifyStates(result); - } - - private static void updateStateForPair(State state, int index, int pairCode, ICollection result) - { - State stateNoBinary = state.endBinaryShift(index); - // Possibility 1. Latch to MODE_PUNCT, and then append this code - result.Add(stateNoBinary.latchAndAppend(MODE_PUNCT, pairCode)); - if (state.Mode != MODE_PUNCT) - { - // Possibility 2. Shift to MODE_PUNCT, and then append this code. - // Every state except MODE_PUNCT (handled above) can shift - result.Add(stateNoBinary.shiftAndAppend(MODE_PUNCT, pairCode)); - } - if (pairCode == 3 || pairCode == 4) - { - // both characters are in DIGITS. Sometimes better to just add two digits - State digit_state = stateNoBinary - .latchAndAppend(MODE_DIGIT, 16 - pairCode) // period or comma in DIGIT - .latchAndAppend(MODE_DIGIT, 1); // space in DIGIT - result.Add(digit_state); - } - if (state.BinaryShiftByteCount > 0) - { - // It only makes sense to do the characters as binary if we're already - // in binary mode. - State binaryState = state.addBinaryShiftChar(index).addBinaryShiftChar(index + 1); - result.Add(binaryState); - } - } - - private static ICollection simplifyStates(IEnumerable states) - { - var result = new LinkedList(); - var removeList = new List(); - foreach (State newState in states) - { - bool add = true; - removeList.Clear(); - foreach (var oldState in result) - { - if (oldState.isBetterThanOrEqualTo(newState)) - { - add = false; - break; - } - if (newState.isBetterThanOrEqualTo(oldState)) - { - removeList.Add(oldState); - } - } - if (add) - { - result.AddLast(newState); - } - foreach (var removeItem in removeList) - { - result.Remove(removeItem); - } - } - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/encoder/SimpleToken.cs b/zxing.core/xx/aztec/encoder/SimpleToken.cs deleted file mode 100644 index 290dfdc..0000000 --- a/zxing.core/xx/aztec/encoder/SimpleToken.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -using ZXing.Common; - -namespace ZXing.Aztec.Internal -{ - public sealed class SimpleToken : Token - { - // For normal words, indicates value and bitCount - private readonly short value; - private readonly short bitCount; - - public SimpleToken(Token previous, int value, int bitCount) - : base(previous) - { - this.value = (short) value; - this.bitCount = (short) bitCount; - } - - public override void appendTo(BitArray bitArray, byte[] text) - { - bitArray.appendBits(value, bitCount); - } - - public override String ToString() - { - int value = this.value & ((1 << bitCount) - 1); - value |= 1 << bitCount; - return '<' + SupportClass.ToBinaryString(value | (1 << bitCount)).Substring(1) + '>'; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/encoder/State.cs b/zxing.core/xx/aztec/encoder/State.cs deleted file mode 100644 index 249743b..0000000 --- a/zxing.core/xx/aztec/encoder/State.cs +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.Aztec.Internal -{ - /// - /// State represents all information about a sequence necessary to generate the current output. - /// Note that a state is immutable. - /// - internal sealed class State - { - public static readonly State INITIAL_STATE = new State(Token.EMPTY, HighLevelEncoder.MODE_UPPER, 0, 0); - - // The current mode of the encoding (or the mode to which we'll return if - // we're in Binary Shift mode. - private readonly int mode; - // The list of tokens that we output. If we are in Binary Shift mode, this - // token list does *not* yet included the token for those bytes - private readonly Token token; - // If non-zero, the number of most recent bytes that should be output - // in Binary Shift mode. - private readonly int binaryShiftByteCount; - // The total number of bits generated (including Binary Shift). - private readonly int bitCount; - - public State(Token token, int mode, int binaryBytes, int bitCount) - { - this.token = token; - this.mode = mode; - this.binaryShiftByteCount = binaryBytes; - this.bitCount = bitCount; - // Make sure we match the token - //int binaryShiftBitCount = (binaryShiftByteCount * 8) + - // (binaryShiftByteCount == 0 ? 0 : - // binaryShiftByteCount <= 31 ? 10 : - // binaryShiftByteCount <= 62 ? 20 : 21); - //assert this.bitCount == token.getTotalBitCount() + binaryShiftBitCount; - } - - public int Mode - { - get { return mode; } - } - - public Token Token - { - get { return token; } - } - - public int BinaryShiftByteCount - { - get { return binaryShiftByteCount; } - } - - public int BitCount - { - get { return bitCount; } - } - - /// - /// Create a new state representing this state with a latch to a (not - /// necessary different) mode, and then a code. - /// - public State latchAndAppend(int mode, int value) - { - //assert binaryShiftByteCount == 0; - int bitCount = this.bitCount; - Token token = this.token; - if (mode != this.mode) - { - int latch = HighLevelEncoder.LATCH_TABLE[this.mode][mode]; - token = token.add(latch & 0xFFFF, latch >> 16); - bitCount += latch >> 16; - } - int latchModeBitCount = mode == HighLevelEncoder.MODE_DIGIT ? 4 : 5; - token = token.add(value, latchModeBitCount); - return new State(token, mode, 0, bitCount + latchModeBitCount); - } - - /// - /// Create a new state representing this state, with a temporary shift - /// to a different mode to output a single value. - /// - public State shiftAndAppend(int mode, int value) - { - //assert binaryShiftByteCount == 0 && this.mode != mode; - Token token = this.token; - int thisModeBitCount = this.mode == HighLevelEncoder.MODE_DIGIT ? 4 : 5; - // Shifts exist only to UPPER and PUNCT, both with tokens size 5. - token = token.add(HighLevelEncoder.SHIFT_TABLE[this.mode][mode], thisModeBitCount); - token = token.add(value, 5); - return new State(token, this.mode, 0, this.bitCount + thisModeBitCount + 5); - } - - /// - /// Create a new state representing this state, but an additional character - /// output in Binary Shift mode. - /// - public State addBinaryShiftChar(int index) - { - Token token = this.token; - int mode = this.mode; - int bitCount = this.bitCount; - if (this.mode == HighLevelEncoder.MODE_PUNCT || this.mode == HighLevelEncoder.MODE_DIGIT) - { - //assert binaryShiftByteCount == 0; - int latch = HighLevelEncoder.LATCH_TABLE[mode][HighLevelEncoder.MODE_UPPER]; - token = token.add(latch & 0xFFFF, latch >> 16); - bitCount += latch >> 16; - mode = HighLevelEncoder.MODE_UPPER; - } - int deltaBitCount = - (binaryShiftByteCount == 0 || binaryShiftByteCount == 31) ? 18 : - (binaryShiftByteCount == 62) ? 9 : 8; - State result = new State(token, mode, binaryShiftByteCount + 1, bitCount + deltaBitCount); - if (result.binaryShiftByteCount == 2047 + 31) - { - // The string is as long as it's allowed to be. We should end it. - result = result.endBinaryShift(index + 1); - } - return result; - } - - /// - /// Create the state identical to this one, but we are no longer in - /// Binary Shift mode. - /// - public State endBinaryShift(int index) - { - if (binaryShiftByteCount == 0) - { - return this; - } - Token token = this.token; - token = token.addBinaryShift(index - binaryShiftByteCount, binaryShiftByteCount); - //assert token.getTotalBitCount() == this.bitCount; - return new State(token, mode, 0, this.bitCount); - } - - /// - /// Returns true if "this" state is better (or equal) to be in than "that" - /// state under all possible circumstances. - /// - public bool isBetterThanOrEqualTo(State other) - { - int mySize = this.bitCount + (HighLevelEncoder.LATCH_TABLE[this.mode][other.mode] >> 16); - if (other.binaryShiftByteCount > 0 && - (this.binaryShiftByteCount == 0 || this.binaryShiftByteCount > other.binaryShiftByteCount)) - { - mySize += 10; // Cost of entering Binary Shift mode. - } - return mySize <= other.bitCount; - } - - public BitArray toBitArray(byte[] text) - { - // Reverse the tokens, so that they are in the order that they should - // be output - var symbols = new LinkedList(); - for (Token token = endBinaryShift(text.Length).token; token != null; token = token.Previous) - { - symbols.AddFirst(token); - } - BitArray bitArray = new BitArray(); - // Add each token to the result. - foreach (Token symbol in symbols) - { - symbol.appendTo(bitArray, text); - } - //assert bitArray.getSize() == this.bitCount; - return bitArray; - } - - public override String ToString() - { - return String.Format("{0} bits={1} bytes={2}", HighLevelEncoder.MODE_NAMES[mode], bitCount, binaryShiftByteCount); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/aztec/encoder/Token.cs b/zxing.core/xx/aztec/encoder/Token.cs deleted file mode 100644 index 3497b0f..0000000 --- a/zxing.core/xx/aztec/encoder/Token.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2013 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 ZXing.Common; - -namespace ZXing.Aztec.Internal -{ - public abstract class Token - { - public static Token EMPTY = new SimpleToken(null, 0, 0); - - private readonly Token previous; - - protected Token(Token previous) - { - this.previous = previous; - } - - public Token Previous - { - get { return previous; } - } - - public Token add(int value, int bitCount) - { - return new SimpleToken(this, value, bitCount); - } - - public Token addBinaryShift(int start, int byteCount) - { - int bitCount = (byteCount*8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21); - return new BinaryShiftToken(this, start, byteCount); - } - - public abstract void appendTo(BitArray bitArray, byte[] text); - } -} diff --git a/zxing.core/xx/common/BitArray.cs b/zxing.core/xx/common/BitArray.cs deleted file mode 100644 index 6e6850f..0000000 --- a/zxing.core/xx/common/BitArray.cs +++ /dev/null @@ -1,488 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.Common -{ - /// - /// A simple, fast array of bits, represented compactly by an array of ints internally. - /// - /// Sean Owen - public sealed class BitArray - { - private int[] bits; - private int size; - - public int Size - { - get - { - return size; - } - } - - public int SizeInBytes - { - get - { - return (size + 7) >> 3; - } - } - - public bool this[int i] - { - get - { - return (bits[i >> 5] & (1 << (i & 0x1F))) != 0; - } - set - { - if (value) - bits[i >> 5] |= 1 << (i & 0x1F); - } - } - - public BitArray() - { - this.size = 0; - this.bits = new int[1]; - } - - public BitArray(int size) - { - if (size < 1) - { - throw new ArgumentException("size must be at least 1"); - } - this.size = size; - this.bits = makeArray(size); - } - - // For testing only - private BitArray(int[] bits, int size) - { - this.bits = bits; - this.size = size; - } - - private void ensureCapacity(int size) - { - if (size > bits.Length << 5) - { - int[] newBits = makeArray(size); - System.Array.Copy(bits, 0, newBits, 0, bits.Length); - bits = newBits; - } - } - - /// Flips bit i. - /// - /// - /// bit to set - /// - public void flip(int i) - { - bits[i >> 5] ^= 1 << (i & 0x1F); - } - - private static int numberOfTrailingZeros(int num) - { - var index = (-num & num)%37; - if (index < 0) - index *= -1; - return _lookup[index]; - } - - private static readonly int[] _lookup = - { - 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, - 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 - }; - - /// - /// Gets the next set. - /// - /// first bit to check - /// index of first bit that is set, starting from the given index, or size if none are set - /// at or beyond this given index - public int getNextSet(int from) - { - if (from >= size) - { - return size; - } - int bitsOffset = from >> 5; - int currentBits = bits[bitsOffset]; - // mask off lesser bits first - currentBits &= ~((1 << (from & 0x1F)) - 1); - while (currentBits == 0) - { - if (++bitsOffset == bits.Length) - { - return size; - } - currentBits = bits[bitsOffset]; - } - int result = (bitsOffset << 5) + numberOfTrailingZeros(currentBits); - return result > size ? size : result; - } - - /// - /// see getNextSet(int) - /// - /// index to start looking for unset bit - /// index of next unset bit, or if none are unset until the end - public int getNextUnset(int from) - { - if (from >= size) - { - return size; - } - int bitsOffset = from >> 5; - int currentBits = ~bits[bitsOffset]; - // mask off lesser bits first - currentBits &= ~((1 << (from & 0x1F)) - 1); - while (currentBits == 0) - { - if (++bitsOffset == bits.Length) - { - return size; - } - currentBits = ~bits[bitsOffset]; - } - int result = (bitsOffset << 5) + numberOfTrailingZeros(currentBits); - return result > size ? size : result; - } - - /// Sets a block of 32 bits, starting at bit i. - /// - /// - /// first bit to set - /// - /// the new value of the next 32 bits. Note again that the least-significant bit - /// corresponds to bit i, the next-least-significant to i+1, and so on. - /// - public void setBulk(int i, int newBits) - { - bits[i >> 5] = newBits; - } - - /// - /// Sets a range of bits. - /// - /// start of range, inclusive. - /// end of range, exclusive - public void setRange(int start, int end) - { - if (end < start) - { - throw new ArgumentException(); - } - if (end == start) - { - return; - } - end--; // will be easier to treat this as the last actually set bit -- inclusive - int firstInt = start >> 5; - int lastInt = end >> 5; - for (int i = firstInt; i <= lastInt; i++) - { - int firstBit = i > firstInt ? 0 : start & 0x1F; - int lastBit = i < lastInt ? 31 : end & 0x1F; - int mask; - if (firstBit == 0 && lastBit == 31) - { - mask = -1; - } - else - { - mask = 0; - for (int j = firstBit; j <= lastBit; j++) - { - mask |= 1 << j; - } - } - bits[i] |= mask; - } - } - - /// Clears all bits (sets to false). - public void clear() - { - int max = bits.Length; - for (int i = 0; i < max; i++) - { - bits[i] = 0; - } - } - - /// Efficient method to check if a range of bits is set, or not set. - /// - /// - /// start of range, inclusive. - /// - /// end of range, exclusive - /// - /// if true, checks that bits in range are set, otherwise checks that they are not set - /// - /// true iff all bits are set or not set in range, according to value argument - /// - /// IllegalArgumentException if end is less than or equal to start - public bool isRange(int start, int end, bool value) - { - if (end < start) - { - throw new System.ArgumentException(); - } - if (end == start) - { - return true; // empty range matches - } - end--; // will be easier to treat this as the last actually set bit -- inclusive - int firstInt = start >> 5; - int lastInt = end >> 5; - for (int i = firstInt; i <= lastInt; i++) - { - int firstBit = i > firstInt ? 0 : start & 0x1F; - int lastBit = i < lastInt ? 31 : end & 0x1F; - int mask; - if (firstBit == 0 && lastBit == 31) - { - mask = -1; - } - else - { - mask = 0; - for (int j = firstBit; j <= lastBit; j++) - { - mask |= 1 << j; - } - } - - // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is, - // equals the mask, or we're looking for 0s and the masked portion is not all 0s - if ((bits[i] & mask) != (value ? mask : 0)) - { - return false; - } - } - return true; - } - - /// - /// Appends the bit. - /// - /// The bit. - public void appendBit(bool bit) - { - ensureCapacity(size + 1); - if (bit) - { - bits[size >> 5] |= 1 << (size & 0x1F); - } - size++; - } - - /// underlying array of ints. The first element holds the first 32 bits, and the least - /// significant bit is bit 0. - /// - public int[] Array - { - get { return bits; } - } - - /// - /// Appends the least-significant bits, from value, in order from most-significant to - /// least-significant. For example, appending 6 bits from 0x000001E will append the bits - /// 0, 1, 1, 1, 1, 0 in that order. - /// - /// containing bits to append - /// bits from value to append - public void appendBits(int value, int numBits) - { - if (numBits < 0 || numBits > 32) - { - throw new ArgumentException("Num bits must be between 0 and 32"); - } - ensureCapacity(size + numBits); - for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) - { - appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1); - } - } - - public void appendBitArray(BitArray other) - { - int otherSize = other.size; - ensureCapacity(size + otherSize); - for (int i = 0; i < otherSize; i++) - { - appendBit(other[i]); - } - } - - public void xor(BitArray other) - { - if (bits.Length != other.bits.Length) - { - throw new ArgumentException("Sizes don't match"); - } - for (int i = 0; i < bits.Length; i++) - { - // The last byte could be incomplete (i.e. not have 8 bits in - // it) but there is no problem since 0 XOR 0 == 0. - bits[i] ^= other.bits[i]; - } - } - - /// - /// Toes the bytes. - /// - /// first bit to start writing - /// array to write into. Bytes are written most-significant byte first. This is the opposite - /// of the internal representation, which is exposed by BitArray - /// position in array to start writing - /// how many bytes to write - public void toBytes(int bitOffset, byte[] array, int offset, int numBytes) - { - for (int i = 0; i < numBytes; i++) - { - int theByte = 0; - for (int j = 0; j < 8; j++) - { - if (this[bitOffset]) - { - theByte |= 1 << (7 - j); - } - bitOffset++; - } - array[offset + i] = (byte)theByte; - } - } - - /// Reverses all bits in the array. - public void reverse() - { - var newBits = new int[bits.Length]; - // reverse all int's first - var len = ((size - 1) >> 5); - var oldBitsLen = len + 1; - for (var i = 0; i < oldBitsLen; i++) - { - var x = (long)bits[i]; - x = ((x >> 1) & 0x55555555u) | ((x & 0x55555555u) << 1); - x = ((x >> 2) & 0x33333333u) | ((x & 0x33333333u) << 2); - x = ((x >> 4) & 0x0f0f0f0fu) | ((x & 0x0f0f0f0fu) << 4); - x = ((x >> 8) & 0x00ff00ffu) | ((x & 0x00ff00ffu) << 8); - x = ((x >> 16) & 0x0000ffffu) | ((x & 0x0000ffffu) << 16); - newBits[len - i] = (int)x; - } - // now correct the int's if the bit size isn't a multiple of 32 - if (size != oldBitsLen * 32) - { - var leftOffset = oldBitsLen * 32 - size; - var mask = 1; - for (var i = 0; i < 31 - leftOffset; i++) - mask = (mask << 1) | 1; - var currentInt = (newBits[0] >> leftOffset) & mask; - for (var i = 1; i < oldBitsLen; i++) - { - var nextInt = newBits[i]; - currentInt |= nextInt << (32 - leftOffset); - newBits[i - 1] = currentInt; - currentInt = (nextInt >> leftOffset) & mask; - } - newBits[oldBitsLen - 1] = currentInt; - } - bits = newBits; - } - - private static int[] makeArray(int size) - { - return new int[(size + 31) >> 5]; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(Object o) - { - var other = o as BitArray; - if (other == null) - return false; - if (size != other.size) - return false; - for (var index = 0; index < size; index++) - { - if (bits[index] != other.bits[index]) - return false; - } - return true; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - var hash = size; - foreach (var bit in bits) - { - hash = 31 * hash + bit.GetHashCode(); - } - return hash; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - var result = new System.Text.StringBuilder(size); - for (int i = 0; i < size; i++) - { - if ((i & 0x07) == 0) - { - result.Append(' '); - } - result.Append(this[i] ? 'X' : '.'); - } - return result.ToString(); - } - - /// - /// Erstellt ein neues Objekt, das eine Kopie der aktuellen Instanz darstellt. - /// - /// - /// Ein neues Objekt, das eine Kopie dieser Instanz darstellt. - /// - public object Clone() - { - return new BitArray((int[])bits.Clone(), size); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/BitMatrix.cs b/zxing.core/xx/common/BitMatrix.cs deleted file mode 100644 index c277ddf..0000000 --- a/zxing.core/xx/common/BitMatrix.cs +++ /dev/null @@ -1,589 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Text; - -namespace ZXing.Common -{ - /// - ///

Represents a 2D matrix of bits. In function arguments below, and throughout the common - /// module, x is the column position, and y is the row position. The ordering is always x, y. - /// The origin is at the top-left.

- ///

Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins - /// with a new int. This is done intentionally so that we can copy out a row into a BitArray very - /// efficiently.

- ///

The ordering of bits is row-major. Within each int, the least significant bits are used first, - /// meaning they represent lower x values. This is compatible with BitArray's implementation.

- ///
- /// Sean Owen - /// dswitkin@google.com (Daniel Switkin) - public sealed partial class BitMatrix - { - private readonly int width; - private readonly int height; - private readonly int rowSize; - private readonly int[] bits; - - /// The width of the matrix - /// - public int Width - { - get { return width; } - } - - /// The height of the matrix - /// - public int Height - { - get { return height; } - } - - /// This method is for compatibility with older code. It's only logical to call if the matrix - /// is square, so I'm throwing if that's not the case. - /// - /// - /// row/column dimension of this matrix - /// - public int Dimension - { - get - { - if (width != height) - { - throw new ArgumentException("Can't call Dimension on a non-square matrix"); - } - return width; - } - - } - - /// - /// The rowsize of the matrix - /// - public int RowSize - { - get { return rowSize; } - } - - // A helper to construct a square matrix. - public BitMatrix(int dimension) - : this(dimension, dimension) - { - } - - public BitMatrix(int width, int height) - { - if (width < 1 || height < 1) - { - throw new System.ArgumentException("Both dimensions must be greater than 0"); - } - this.width = width; - this.height = height; - this.rowSize = (width + 31) >> 5; - bits = new int[rowSize*height]; - } - - internal BitMatrix(int width, int height, int rowSize, int[] bits) - { - this.width = width; - this.height = height; - this.rowSize = rowSize; - this.bits = bits; - } - - internal BitMatrix(int width, int height, int[] bits) - { - this.width = width; - this.height = height; - this.rowSize = (width + 31) >> 5; - this.bits = bits; - } - - public static BitMatrix parse(String stringRepresentation, String setString, String unsetString) - { - if (stringRepresentation == null) - { - throw new ArgumentException(); - } - - bool[] bits = new bool[stringRepresentation.Length]; - int bitsPos = 0; - int rowStartPos = 0; - int rowLength = -1; - int nRows = 0; - int pos = 0; - while (pos < stringRepresentation.Length) - { - if (stringRepresentation.Substring(pos, 1).Equals("\n") || - stringRepresentation.Substring(pos, 1).Equals("\r")) - { - if (bitsPos > rowStartPos) - { - if (rowLength == -1) - { - rowLength = bitsPos - rowStartPos; - } - else if (bitsPos - rowStartPos != rowLength) - { - throw new ArgumentException("row lengths do not match"); - } - rowStartPos = bitsPos; - nRows++; - } - pos++; - } - else if (stringRepresentation.Substring(pos, setString.Length).Equals(setString)) - { - pos += setString.Length; - bits[bitsPos] = true; - bitsPos++; - } - else if (stringRepresentation.Substring(pos, unsetString.Length).Equals(unsetString)) - { - pos += unsetString.Length; - bits[bitsPos] = false; - bitsPos++; - } - else - { - throw new ArgumentException("illegal character encountered: " + stringRepresentation.Substring(pos)); - } - } - - // no EOL at end? - if (bitsPos > rowStartPos) - { - if (rowLength == -1) - { - rowLength = bitsPos - rowStartPos; - } - else if (bitsPos - rowStartPos != rowLength) - { - throw new ArgumentException("row lengths do not match"); - } - nRows++; - } - - BitMatrix matrix = new BitMatrix(rowLength, nRows); - for (int i = 0; i < bitsPos; i++) - { - if (bits[i]) - { - matrix[i%rowLength, i/rowLength] = true; - } - } - return matrix; - } - - ///

Gets the requested bit, where true means black.

- /// - ///
- /// The horizontal component (i.e. which column) - /// - /// The vertical component (i.e. which row) - /// - /// value of given bit in matrix - /// - public bool this[int x, int y] - { - get - { - int offset = y*rowSize + (x >> 5); - return (((int) ((uint) (bits[offset]) >> (x & 0x1f))) & 1) != 0; - } - set - { - if (value) - { - int offset = y*rowSize + (x >> 5); - bits[offset] |= 1 << (x & 0x1f); - } - else - { - int offset = y*rowSize + (x/32); - bits[offset] &= ~(1 << (x & 0x1f)); - } - } - } - - ///

Flips the given bit.

- /// - ///
- /// The horizontal component (i.e. which column) - /// - /// The vertical component (i.e. which row) - /// - public void flip(int x, int y) - { - int offset = y*rowSize + (x >> 5); - bits[offset] ^= 1 << (x & 0x1f); - } - - /// - /// Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding - /// mask bit is set. - /// - /// The mask. - public void xor(BitMatrix mask) - { - if (width != mask.Width || height != mask.Height - || rowSize != mask.RowSize) - { - throw new ArgumentException("input matrix dimensions do not match"); - } - var rowArray = new BitArray(width/32 + 1); - for (int y = 0; y < height; y++) - { - int offset = y*rowSize; - int[] row = mask.getRow(y, rowArray).Array; - for (int x = 0; x < rowSize; x++) - { - bits[offset + x] ^= row[x]; - } - } - } - - /// Clears all bits (sets to false). - public void clear() - { - int max = bits.Length; - for (int i = 0; i < max; i++) - { - bits[i] = 0; - } - } - - ///

Sets a square region of the bit matrix to true.

- /// - ///
- /// The horizontal position to begin at (inclusive) - /// - /// The vertical position to begin at (inclusive) - /// - /// The width of the region - /// - /// The height of the region - /// - public void setRegion(int left, int top, int width, int height) - { - if (top < 0 || left < 0) - { - throw new System.ArgumentException("Left and top must be nonnegative"); - } - if (height < 1 || width < 1) - { - throw new System.ArgumentException("Height and width must be at least 1"); - } - int right = left + width; - int bottom = top + height; - if (bottom > this.height || right > this.width) - { - throw new System.ArgumentException("The region must fit inside the matrix"); - } - for (int y = top; y < bottom; y++) - { - int offset = y*rowSize; - for (int x = left; x < right; x++) - { - bits[offset + (x >> 5)] |= 1 << (x & 0x1f); - } - } - } - - /// A fast method to retrieve one row of data from the matrix as a BitArray. - /// - /// - /// The row to retrieve - /// - /// An optional caller-allocated BitArray, will be allocated if null or too small - /// - /// The resulting BitArray - this reference should always be used even when passing - /// your own row - /// - public BitArray getRow(int y, BitArray row) - { - if (row == null || row.Size < width) - { - row = new BitArray(width); - } - else - { - row.clear(); - } - int offset = y*rowSize; - for (int x = 0; x < rowSize; x++) - { - row.setBulk(x << 5, bits[offset + x]); - } - return row; - } - - /// - /// Sets the row. - /// - /// row to set - /// {@link BitArray} to copy from - public void setRow(int y, BitArray row) - { - Array.Copy(row.Array, 0, bits, y*rowSize, rowSize); - } - - /// - /// Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees - /// - public void rotate180() - { - var width = Width; - var height = Height; - var topRow = new BitArray(width); - var bottomRow = new BitArray(width); - for (int i = 0; i < (height + 1)/2; i++) - { - topRow = getRow(i, topRow); - bottomRow = getRow(height - 1 - i, bottomRow); - topRow.reverse(); - bottomRow.reverse(); - setRow(i, bottomRow); - setRow(height - 1 - i, topRow); - } - } - - /// - /// This is useful in detecting the enclosing rectangle of a 'pure' barcode. - /// - /// {left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white - public int[] getEnclosingRectangle() - { - int left = width; - int top = height; - int right = -1; - int bottom = -1; - - for (int y = 0; y < height; y++) - { - for (int x32 = 0; x32 < rowSize; x32++) - { - int theBits = bits[y*rowSize + x32]; - if (theBits != 0) - { - if (y < top) - { - top = y; - } - if (y > bottom) - { - bottom = y; - } - if (x32*32 < left) - { - int bit = 0; - while ((theBits << (31 - bit)) == 0) - { - bit++; - } - if ((x32*32 + bit) < left) - { - left = x32*32 + bit; - } - } - if (x32*32 + 31 > right) - { - int bit = 31; - while (((int) ((uint) theBits >> bit)) == 0) // (theBits >>> bit) - { - bit--; - } - if ((x32*32 + bit) > right) - { - right = x32*32 + bit; - } - } - } - } - } - - int widthTmp = right - left; - int heightTmp = bottom - top; - - if (widthTmp < 0 || heightTmp < 0) - { - return null; - } - - return new[] {left, top, widthTmp, heightTmp}; - } - - /// - /// This is useful in detecting a corner of a 'pure' barcode. - /// - /// {x,y} coordinate of top-left-most 1 bit, or null if it is all white - public int[] getTopLeftOnBit() - { - int bitsOffset = 0; - while (bitsOffset < bits.Length && bits[bitsOffset] == 0) - { - bitsOffset++; - } - if (bitsOffset == bits.Length) - { - return null; - } - int y = bitsOffset/rowSize; - int x = (bitsOffset%rowSize) << 5; - - int theBits = bits[bitsOffset]; - int bit = 0; - while ((theBits << (31 - bit)) == 0) - { - bit++; - } - x += bit; - return new[] {x, y}; - } - - public int[] getBottomRightOnBit() - { - int bitsOffset = bits.Length - 1; - while (bitsOffset >= 0 && bits[bitsOffset] == 0) - { - bitsOffset--; - } - if (bitsOffset < 0) - { - return null; - } - - int y = bitsOffset/rowSize; - int x = (bitsOffset%rowSize) << 5; - - int theBits = bits[bitsOffset]; - int bit = 31; - - while (((int) ((uint) theBits >> bit)) == 0) // (theBits >>> bit) - { - bit--; - } - x += bit; - - return new int[] {x, y}; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(object obj) - { - if (!(obj is BitMatrix)) - { - return false; - } - var other = (BitMatrix) obj; - if (width != other.width || height != other.height || - rowSize != other.rowSize || bits.Length != other.bits.Length) - { - return false; - } - for (int i = 0; i < bits.Length; i++) - { - if (bits[i] != other.bits[i]) - { - return false; - } - } - return true; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - int hash = width; - hash = 31*hash + width; - hash = 31*hash + height; - hash = 31*hash + rowSize; - foreach (var bit in bits) - { - hash = 31*hash + bit.GetHashCode(); - } - return hash; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - return ToString("X ", " ", Environment.NewLine); - } - - /// - /// Returns a that represents this instance. - /// - /// The set string. - /// The unset string. - /// - /// A that represents this instance. - /// - public String ToString(String setString, String unsetString) - { - return ToString(setString, unsetString, Environment.NewLine); - } - - /// - /// Returns a that represents this instance. - /// - /// The set string. - /// The unset string. - /// The line separator. - /// - /// A that represents this instance. - /// - public String ToString(String setString, String unsetString, String lineSeparator) - { - var result = new StringBuilder(height*(width + 1)); - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - result.Append(this[x, y] ? setString : unsetString); - } - result.Append(lineSeparator); - } - return result.ToString(); - } - - /// - /// Clones this instance. - /// - /// - public object Clone() - { - return new BitMatrix(width, height, rowSize, (int[]) bits.Clone()); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/BitSource.cs b/zxing.core/xx/common/BitSource.cs deleted file mode 100644 index 2f3583e..0000000 --- a/zxing.core/xx/common/BitSource.cs +++ /dev/null @@ -1,124 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.Common -{ - ///

This provides an easy abstraction to read bits at a time from a sequence of bytes, where the - /// number of bits read is not often a multiple of 8.

- /// - ///

This class is thread-safe but not reentrant. Unless the caller modifies the bytes array - /// it passed in, in which case all bets are off.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public sealed class BitSource - { - private readonly byte[] bytes; - private int byteOffset; - private int bitOffset; - - /// bytes from which this will read bits. Bits will be read from the first byte first. - /// Bits are read within a byte from most-significant to least-significant bit. - /// - public BitSource(byte[] bytes) - { - this.bytes = bytes; - } - - /// - /// index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. - /// - public int BitOffset - { - get { return bitOffset; } - } - - /// - /// index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. - /// - public int ByteOffset - { - get { return byteOffset; } - } - - /// number of bits to read - /// - /// int representing the bits read. The bits will appear as the least-significant - /// bits of the int - /// - /// if numBits isn't in [1,32] or more than is available - public int readBits(int numBits) - { - if (numBits < 1 || numBits > 32 || numBits > available()) - { - throw new ArgumentException(numBits.ToString(), "numBits"); - } - - int result = 0; - - // First, read remainder from current byte - if (bitOffset > 0) - { - int bitsLeft = 8 - bitOffset; - int toRead = numBits < bitsLeft ? numBits : bitsLeft; - int bitsToNotRead = bitsLeft - toRead; - int mask = (0xFF >> (8 - toRead)) << bitsToNotRead; - result = (bytes[byteOffset] & mask) >> bitsToNotRead; - numBits -= toRead; - bitOffset += toRead; - if (bitOffset == 8) - { - bitOffset = 0; - byteOffset++; - } - } - - // Next read whole bytes - if (numBits > 0) - { - while (numBits >= 8) - { - result = (result << 8) | (bytes[byteOffset] & 0xFF); - byteOffset++; - numBits -= 8; - } - - // Finally read a partial byte - if (numBits > 0) - { - int bitsToNotRead = 8 - numBits; - int mask = (0xFF >> bitsToNotRead) << bitsToNotRead; - result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead); - bitOffset += numBits; - } - } - - return result; - } - - /// number of bits that can be read successfully - /// - public int available() - { - return 8 * (bytes.Length - byteOffset) - bitOffset; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/CharacterSetECI.cs b/zxing.core/xx/common/CharacterSetECI.cs deleted file mode 100644 index f75ea10..0000000 --- a/zxing.core/xx/common/CharacterSetECI.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -namespace ZXing.Common -{ - /// Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1 - /// of ISO 18004. - /// - /// - /// Sean Owen - public sealed class CharacterSetECI : ECI - { - internal static readonly IDictionary VALUE_TO_ECI; - internal static readonly IDictionary NAME_TO_ECI; - - private readonly String encodingName; - - public String EncodingName - { - get - { - return encodingName; - } - - } - - static CharacterSetECI() - { - VALUE_TO_ECI = new Dictionary(); - NAME_TO_ECI = new Dictionary(); - // 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; - } - } - - /// character set ECI value - /// representing ECI of given value, or null if it is legal but unsupported - public static CharacterSetECI getCharacterSetECIByValue(int value) - { - if (value < 0 || value >= 900) - { - return null; - } - return VALUE_TO_ECI[value]; - } - - /// character set ECI encoding name - /// representing ECI for character encoding, or null if it is legalbut unsupported - public static CharacterSetECI getCharacterSetECIByName(String name) - { - return NAME_TO_ECI[name.ToUpper()]; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/DecoderResult.cs b/zxing.core/xx/common/DecoderResult.cs deleted file mode 100644 index a12a1c8..0000000 --- a/zxing.core/xx/common/DecoderResult.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -namespace ZXing.Common -{ - /// - /// Encapsulates the result of decoding a matrix of bits. This typically - /// applies to 2D barcode formats. For now it contains the raw bytes obtained, - /// as well as a String interpretation of those bytes, if applicable. - /// Sean Owen - /// - public sealed class DecoderResult - { - public byte[] RawBytes { get; private set; } - - public String Text { get; private set; } - - public IList ByteSegments { get; private set; } - - public String ECLevel { get; private set; } - - public bool StructuredAppend - { - get { return StructuredAppendParity >= 0 && StructuredAppendSequenceNumber >= 0; } - } - - public int ErrorsCorrected { get; set; } - - public int StructuredAppendSequenceNumber { get; private set; } - - public int Erasures { get; set; } - - public int StructuredAppendParity { get; private set; } - - /// - /// Miscellanseous data value for the various decoders - /// - /// The other. - public object Other { get; set; } - - public DecoderResult(byte[] rawBytes, String text, IList byteSegments, String ecLevel) - : this(rawBytes, text, byteSegments, ecLevel, -1, -1) - { - } - - public DecoderResult(byte[] rawBytes, String text, IList byteSegments, String ecLevel, int saSequence, int saParity) - { - if (rawBytes == null && text == null) - { - throw new ArgumentException(); - } - RawBytes = rawBytes; - Text = text; - ByteSegments = byteSegments; - ECLevel = ecLevel; - StructuredAppendParity = saParity; - StructuredAppendSequenceNumber = saSequence; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/DecodingOptions.cs b/zxing.core/xx/common/DecodingOptions.cs deleted file mode 100644 index 026a748..0000000 --- a/zxing.core/xx/common/DecodingOptions.cs +++ /dev/null @@ -1,485 +0,0 @@ -/* - * 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 -{ - /// - /// Defines an container for encoder options - /// - public class DecodingOptions - { - /// - /// Gets the data container for all options - /// - public IDictionary Hints { get; private set; } - - public event Action ValueChanged; - - /// - /// Gets or sets a flag which cause a deeper look into the bitmap - /// - /// - /// true if [try harder]; otherwise, false. - /// - 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); - } - } - } - } - - /// - /// Image is a pure monochrome image of a barcode. - /// - /// - /// true if monochrome image of a barcode; otherwise, false. - /// - 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); - } - } - } - } - - /// - /// Specifies what character encoding to use when decoding, where applicable (type String) - /// - /// - /// The character set. - /// - 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); - } - } - } - } - - /// - /// Image is known to be of one of a few possible formats. - /// Maps to a {@link java.util.List} of {@link BarcodeFormat}s. - /// - /// - /// The possible formats. - /// - public IList PossibleFormats - { - get - { - if (Hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS)) - return (IList)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); - } - } - } - } - - /// - /// if Code39 could be detected try to use extended mode for full ASCII character set - /// - 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); - } - } - } - } - - /// - /// Don't fail if a Code39 is detected but can't be decoded in extended mode. - /// Return the raw Code39 result instead. Maps to . - /// - 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); - } - } - } - } - - /// - /// 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 . - /// - 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); - } - } - } - } - - /// - /// Assume the barcode is being processed as a GS1 barcode, and modify behavior as needed. - /// For example this affects FNC1 handling for Code 128 (aka GS1-128). - /// - /// - /// true if it should assume GS1; otherwise, false. - /// - public bool AssumeGS1 - { - get - { - if (Hints.ContainsKey(DecodeHintType.ASSUME_GS1)) - return (bool)Hints[DecodeHintType.ASSUME_GS1]; - return false; - } - set - { - if (value) - { - Hints[DecodeHintType.ASSUME_GS1] = true; - } - else - { - if (Hints.ContainsKey(DecodeHintType.ASSUME_GS1)) - { - Hints.Remove(DecodeHintType.ASSUME_GS1); - } - } - } - } - - /// - /// Assume MSI codes employ a check digit. Maps to . - /// - /// - /// true if it should assume a MSI check digit; otherwise, false. - /// - public bool AssumeMSICheckDigit - { - get - { - if (Hints.ContainsKey(DecodeHintType.ASSUME_MSI_CHECK_DIGIT)) - return (bool)Hints[DecodeHintType.ASSUME_MSI_CHECK_DIGIT]; - return false; - } - set - { - if (value) - { - Hints[DecodeHintType.ASSUME_MSI_CHECK_DIGIT] = true; - } - else - { - if (Hints.ContainsKey(DecodeHintType.ASSUME_MSI_CHECK_DIGIT)) - { - Hints.Remove(DecodeHintType.ASSUME_MSI_CHECK_DIGIT); - } - } - } - } - - /// - /// Allowed lengths of encoded data -- reject anything else. Maps to an int[]. - /// - public int[] AllowedLengths - { - get - { - if (Hints.ContainsKey(DecodeHintType.ALLOWED_LENGTHS)) - return (int[])Hints[DecodeHintType.ALLOWED_LENGTHS]; - return null; - } - set - { - if (value != null && value.Length > 0) - { - Hints[DecodeHintType.ALLOWED_LENGTHS] = value; - } - else - { - if (Hints.ContainsKey(DecodeHintType.ALLOWED_LENGTHS)) - { - Hints.Remove(DecodeHintType.ALLOWED_LENGTHS); - } - } - } - } - - /// - /// Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this. - /// Maps to an of the allowed extension lengths, for example [2], [5], or [2, 5]. - /// If it is optional to have an extension, do not set this hint. If this is set, - /// and a UPC or EAN barcode is found but an extension is not, then no result will be returned - /// at all. - /// - public int[] AllowedEANExtensions - { - get - { - if (Hints.ContainsKey(DecodeHintType.ALLOWED_EAN_EXTENSIONS)) - return (int[])Hints[DecodeHintType.ALLOWED_EAN_EXTENSIONS]; - return null; - } - set - { - if (value != null && value.Length > 0) - { - Hints[DecodeHintType.ALLOWED_EAN_EXTENSIONS] = value; - } - else - { - if (Hints.ContainsKey(DecodeHintType.ALLOWED_EAN_EXTENSIONS)) - { - Hints.Remove(DecodeHintType.ALLOWED_EAN_EXTENSIONS); - } - } - } - } - - /// - /// Initializes a new instance of the class. - /// - public DecodingOptions() - { - var hints = new ChangeNotifyDictionary(); - Hints = hints; - UseCode39ExtendedMode = true; - UseCode39RelaxedExtendedMode = true; - hints.ValueChanged += (o, args) => { if (ValueChanged != null) ValueChanged(this, EventArgs.Empty); }; - } - - private class ChangeNotifyDictionary: IDictionary - { - private readonly IDictionary values; - - public event Action ValueChanged; - - public ChangeNotifyDictionary() - { - values = new Dictionary(); - } - - 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 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 Values - { - get { return values.Values; } - } - - public TValue this[TKey key] - { - get - { - return values[key]; - } - set - { - values[key] = value; - OnValueChanged(); - } - } - - public void Add(KeyValuePair item) - { - values.Add(item); - OnValueChanged(); - } - - public void Clear() - { - values.Clear(); - OnValueChanged(); - } - - public bool Contains(KeyValuePair item) - { - return values.Contains(item); - } - - public void CopyTo(KeyValuePair[] 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 item) - { - var result = values.Remove(item); - OnValueChanged(); - - return result; - } - - public IEnumerator> GetEnumerator() - { - return values.GetEnumerator(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return ((System.Collections.IEnumerable)values).GetEnumerator(); - } - } - } -} diff --git a/zxing.core/xx/common/DefaultGridSampler.cs b/zxing.core/xx/common/DefaultGridSampler.cs deleted file mode 100644 index 4e60db4..0000000 --- a/zxing.core/xx/common/DefaultGridSampler.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -using System; - -namespace ZXing.Common -{ - - /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public sealed class DefaultGridSampler : GridSampler - { - public override BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, float p1ToX, float p1ToY, float p2ToX, float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY) - { - PerspectiveTransform transform = PerspectiveTransform.quadrilateralToQuadrilateral( - p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, - p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY); - return sampleGrid(image, dimensionX, dimensionY, transform); - } - - public override BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, PerspectiveTransform transform) - { - if (dimensionX <= 0 || dimensionY <= 0) - { - return null; - } - BitMatrix bits = new BitMatrix(dimensionX, dimensionY); - float[] points = new float[dimensionX << 1]; - for (int y = 0; y < dimensionY; y++) - { - int max = points.Length; - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - float iValue = (float)y + 0.5f; - for (int x = 0; x < max; x += 2) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - points[x] = (float)(x >> 1) + 0.5f; - points[x + 1] = iValue; - } - transform.transformPoints(points); - // Quick check to see if points transformed to something inside the image; - // sufficient to check the endpoints - if (!checkAndNudgePoints(image, points)) - return null; - try - { - for (int x = 0; x < max; x += 2) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - bits[x >> 1, y] = image[(int)points[x], (int)points[x + 1]]; - } - } - catch (System.IndexOutOfRangeException) - { - // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting - // transform gets "twisted" such that it maps a straight line of points to a set of points - // whose endpoints are in bounds, but others are not. There is probably some mathematical - // way to detect this about the transformation that I don't know yet. - // This results in an ugly runtime exception despite our clever checks above -- can't have - // that. We could check each point's coordinates but that feels duplicative. We settle for - // catching and wrapping ArrayIndexOutOfBoundsException. - return null; - } - } - return bits; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/DetectorResult.cs b/zxing.core/xx/common/DetectorResult.cs deleted file mode 100644 index 3fd3756..0000000 --- a/zxing.core/xx/common/DetectorResult.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.Common -{ - ///

Encapsulates the result of detecting a barcode in an image. This includes the raw - /// matrix of black/white pixels corresponding to the barcode, and possibly points of interest - /// in the image, like the location of finder patterns or corners of the barcode in the image.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public class DetectorResult - { - public BitMatrix Bits { get; private set; } - public ResultPoint[] Points { get; private set; } - - public DetectorResult(BitMatrix bits, ResultPoint[] points) - { - Bits = bits; - Points = points; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/ECI.cs b/zxing.core/xx/common/ECI.cs deleted file mode 100644 index 5d0fc3c..0000000 --- a/zxing.core/xx/common/ECI.cs +++ /dev/null @@ -1,66 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -using System; -namespace ZXing.Common -{ - - /// Superclass of classes encapsulating types ECIs, according to "Extended Channel Interpretations" - /// 5.3 of ISO 18004. - /// - /// - /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - 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; - } - - /// ECI value - /// - /// {@link ECI} representing ECI of given value, or null if it is legal but unsupported - /// - /// IllegalArgumentException if ECI value is invalid - 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; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/EncodingOptions.cs b/zxing.core/xx/common/EncodingOptions.cs deleted file mode 100644 index b247381..0000000 --- a/zxing.core/xx/common/EncodingOptions.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 System.ComponentModel; - -namespace ZXing.Common -{ - /// - /// Defines an container for encoder options - /// - public class EncodingOptions - { - /// - /// Gets the data container for all options - /// - public IDictionary Hints { get; private set; } - - /// - /// Specifies the height of the barcode image - /// - public int Height - { - get - { - if (Hints.ContainsKey(EncodeHintType.HEIGHT)) - { - return (int)Hints[EncodeHintType.HEIGHT]; - } - return 0; - } - set - { - Hints[EncodeHintType.HEIGHT] = value; - } - } - - /// - /// Specifies the width of the barcode image - /// - public int Width - { - get - { - if (Hints.ContainsKey(EncodeHintType.WIDTH)) - { - return (int)Hints[EncodeHintType.WIDTH]; - } - return 0; - } - set - { - Hints[EncodeHintType.WIDTH] = value; - } - } - - /// - /// Don't put the content string into the output image. - /// - public bool PureBarcode - { - get - { - if (Hints.ContainsKey(EncodeHintType.PURE_BARCODE)) - { - return (bool)Hints[EncodeHintType.PURE_BARCODE]; - } - return false; - } - set - { - Hints[EncodeHintType.PURE_BARCODE] = value; - } - } - - /// - /// Specifies margin, in pixels, to use when generating the barcode. The meaning can vary - /// by format; for example it controls margin before and after the barcode horizontally for - /// most 1D formats. - /// - public int Margin - { - get - { - if (Hints.ContainsKey(EncodeHintType.MARGIN)) - { - return (int) Hints[EncodeHintType.MARGIN]; - } - return 0; - } - set - { - Hints[EncodeHintType.MARGIN] = value; - } - } - - /// - /// Initializes a new instance of the class. - /// - public EncodingOptions() - { - Hints = new Dictionary(); - } - } -} diff --git a/zxing.core/xx/common/GlobalHistogramBinarizer.cs b/zxing.core/xx/common/GlobalHistogramBinarizer.cs deleted file mode 100644 index 6523116..0000000 --- a/zxing.core/xx/common/GlobalHistogramBinarizer.cs +++ /dev/null @@ -1,243 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.Common -{ - /// 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. - /// - /// dswitkin@google.com (Daniel Switkin) - /// Sean Owen - /// - 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; - - /// - /// Initializes a new instance of the class. - /// - /// The source. - public GlobalHistogramBinarizer(LuminanceSource source) - : base(source) - { - luminances = EMPTY; - buckets = new int[LUMINANCE_BUCKETS]; - } - - /// - /// Applies simple sharpening to the row data to improve performance of the 1D Readers. - /// - /// - /// - /// - 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; - } - - /// - /// Does not sharpen the data, as this call is intended to only be used by 2D Readers. - /// - 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; - } - } - - /// - /// 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. - /// - /// The LuminanceSource this Binarizer will operate on. - /// - /// A new concrete Binarizer implementation object. - /// - 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; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/GridSampler.cs b/zxing.core/xx/common/GridSampler.cs deleted file mode 100644 index 2484b6c..0000000 --- a/zxing.core/xx/common/GridSampler.cs +++ /dev/null @@ -1,197 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.Common -{ - /// Implementations of this class can, given locations of finder patterns for a QR code in an - /// image, sample the right points in the image to reconstruct the QR code, accounting for - /// perspective distortion. It is abstracted since it is relatively expensive and should be allowed - /// to take advantage of platform-specific optimized implementations, like Sun's Java Advanced - /// Imaging library, but which may not be available in other environments such as J2ME, and vice - /// versa. - /// - /// The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)} - /// with an instance of a class which implements this interface. - /// - /// Sean Owen - public abstract class GridSampler - { - /// the current implementation of - /// - public static GridSampler Instance - { - get - { - return gridSampler; - } - - } - - private static GridSampler gridSampler = new DefaultGridSampler(); - - /// Sets the implementation of used by the library. One global - /// instance is stored, which may sound problematic. But, the implementation provided - /// ought to be appropriate for the entire platform, and all uses of this library - /// in the whole lifetime of the JVM. For instance, an Android activity can swap in - /// an implementation that takes advantage of native platform libraries. - /// - /// The platform-specific object to install. - public static void setGridSampler(GridSampler newGridSampler) - { - if (newGridSampler == null) - { - throw new System.ArgumentException(); - } - gridSampler = newGridSampler; - } - - /// - ///

Samples an image for a square matrix of bits of the given dimension. This is used to extract - /// the black/white modules of a 2D barcode like a QR Code found in an image. Because this barcode - /// may be rotated or perspective-distorted, the caller supplies four points in the source image - /// that define known points in the barcode, so that the image may be sampled appropriately.

- ///

The last eight "from" parameters are four X/Y coordinate pairs of locations of points in - /// the image that define some significant points in the image to be sample. For example, - /// these may be the location of finder pattern in a QR Code.

- ///

The first eight "to" parameters are four X/Y coordinate pairs measured in the destination - /// , from the top left, where the known points in the image given by the "from" - /// parameters map to.

- ///

These 16 parameters define the transformation needed to sample the image.

- ///
- /// image to sample - /// The dimension X. - /// The dimension Y. - /// The p1 preimage X. - /// The p1 preimage Y. - /// The p2 preimage X. - /// The p2 preimage Y. - /// The p3 preimage X. - /// The p3 preimage Y. - /// The p4 preimage X. - /// The p4 preimage Y. - /// The p1 image X. - /// The p1 image Y. - /// The p2 image X. - /// The p2 image Y. - /// The p3 image X. - /// The p3 image Y. - /// The p4 image X. - /// The p4 image Y. - /// - /// representing a grid of points sampled from the image within a region - /// defined by the "from" parameters - /// - /// ReaderException if image can't be sampled, for example, if the transformation defined - public abstract BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, float p1ToX, float p1ToY, float p2ToX, float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY); - - public virtual BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, PerspectiveTransform transform) - { - throw new System.NotSupportedException(); - } - - - ///

Checks a set of points that have been transformed to sample points on an image against - /// the image's dimensions to see if the point are even within the image.

- /// - ///

This method will actually "nudge" the endpoints back onto the image if they are found to be - /// barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder - /// patterns in an image where the QR Code runs all the way to the image border.

- /// - ///

For efficiency, the method will check points from either end of the line until one is found - /// to be within the image. Because the set of points are assumed to be linear, this is valid.

- /// - ///
- /// image into which the points should map - /// - /// actual points in x1,y1,...,xn,yn form - /// - protected internal static bool checkAndNudgePoints(BitMatrix image, float[] points) - { - int width = image.Width; - int height = image.Height; - // Check and nudge points from start until we see some that are OK: - bool nudged = true; - for (int offset = 0; offset < points.Length && nudged; offset += 2) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int x = (int)points[offset]; - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int y = (int)points[offset + 1]; - if (x < -1 || x > width || y < -1 || y > height) - { - return false; - } - nudged = false; - if (x == -1) - { - points[offset] = 0.0f; - nudged = true; - } - else if (x == width) - { - points[offset] = width - 1; - nudged = true; - } - if (y == -1) - { - points[offset + 1] = 0.0f; - nudged = true; - } - else if (y == height) - { - points[offset + 1] = height - 1; - nudged = true; - } - } - // Check and nudge points from end: - nudged = true; - for (int offset = points.Length - 2; offset >= 0 && nudged; offset -= 2) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int x = (int)points[offset]; - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int y = (int)points[offset + 1]; - if (x < -1 || x > width || y < -1 || y > height) - { - return false; - } - nudged = false; - if (x == -1) - { - points[offset] = 0.0f; - nudged = true; - } - else if (x == width) - { - points[offset] = width - 1; - nudged = true; - } - if (y == -1) - { - points[offset + 1] = 0.0f; - nudged = true; - } - else if (y == height) - { - points[offset + 1] = height - 1; - nudged = true; - } - } - - return true; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/HybridBinarizer.cs b/zxing.core/xx/common/HybridBinarizer.cs deleted file mode 100644 index 7d39428..0000000 --- a/zxing.core/xx/common/HybridBinarizer.cs +++ /dev/null @@ -1,288 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.Common -{ - /// 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. - /// - /// - /// dswitkin@google.com (Daniel Switkin) - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - 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); - } - - /// - /// Calculates the final BitMatrix once for all requests. This could be called once from the - /// constructor instead, but there are some advantages to doing it lazily, such as making - /// profiling easier, and not doing heavy lifting when callers don't expect it. - /// - private void binarizeEntireImage() - { - if (matrix == null) - { - LuminanceSource source = LuminanceSource; - 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; - } - } - } - - /// - /// 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). - /// - /// The luminances. - /// Width of the sub. - /// Height of the sub. - /// The width. - /// The height. - /// The black points. - /// The matrix. - 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; - } - - /// - /// Applies a single threshold to an 8x8 block of pixels. - /// - /// The luminances. - /// The xoffset. - /// The yoffset. - /// The threshold. - /// The stride. - /// The matrix. - 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); - } - } - } - - /// - /// 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 - /// - /// The luminances. - /// Width of the sub. - /// Height of the sub. - /// The width. - /// The height. - /// - 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; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/PerspectiveTransform.cs b/zxing.core/xx/common/PerspectiveTransform.cs deleted file mode 100644 index 7065635..0000000 --- a/zxing.core/xx/common/PerspectiveTransform.cs +++ /dev/null @@ -1,159 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.Common -{ - ///

This class implements a perspective transform in two dimensions. Given four source and four - /// destination points, it will compute the transformation implied between them. The code is based - /// directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public sealed class PerspectiveTransform - { - private float a11; - private float a12; - private float a13; - private float a21; - private float a22; - private float a23; - private float a31; - private float a32; - private float a33; - - private PerspectiveTransform(float a11, float a21, float a31, float a12, float a22, float a32, float a13, float a23, float a33) - { - this.a11 = a11; - this.a12 = a12; - this.a13 = a13; - this.a21 = a21; - this.a22 = a22; - this.a23 = a23; - this.a31 = a31; - this.a32 = a32; - this.a33 = a33; - } - - public static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, float x3p, float y3p) - { - - PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); - PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); - return sToQ.times(qToS); - } - - public void transformPoints(float[] points) - { - int max = points.Length; - float a11 = this.a11; - float a12 = this.a12; - float a13 = this.a13; - float a21 = this.a21; - float a22 = this.a22; - float a23 = this.a23; - float a31 = this.a31; - float a32 = this.a32; - float a33 = this.a33; - for (int i = 0; i < max; i += 2) - { - float x = points[i]; - float y = points[i + 1]; - float denominator = a13 * x + a23 * y + a33; - points[i] = (a11 * x + a21 * y + a31) / denominator; - points[i + 1] = (a12 * x + a22 * y + a32) / denominator; - } - } - - /// Convenience method, not optimized for performance. - public void transformPoints(float[] xValues, float[] yValues) - { - int n = xValues.Length; - for (int i = 0; i < n; i++) - { - float x = xValues[i]; - float y = yValues[i]; - float denominator = a13 * x + a23 * y + a33; - xValues[i] = (a11 * x + a21 * y + a31) / denominator; - yValues[i] = (a12 * x + a22 * y + a32) / denominator; - } - } - - public static PerspectiveTransform squareToQuadrilateral(float x0, float y0, - float x1, float y1, - float x2, float y2, - float x3, float y3) - { - float dx3 = x0 - x1 + x2 - x3; - float dy3 = y0 - y1 + y2 - y3; - if (dx3 == 0.0f && dy3 == 0.0f) - { - // Affine - return new PerspectiveTransform(x1 - x0, x2 - x1, x0, - y1 - y0, y2 - y1, y0, - 0.0f, 0.0f, 1.0f); - } - else - { - float dx1 = x1 - x2; - float dx2 = x3 - x2; - float dy1 = y1 - y2; - float dy2 = y3 - y2; - float denominator = dx1*dy2 - dx2*dy1; - float a13 = (dx3*dy2 - dx2*dy3)/denominator; - float a23 = (dx1*dy3 - dx3*dy1)/denominator; - return new PerspectiveTransform(x1 - x0 + a13*x1, x3 - x0 + a23*x3, x0, - y1 - y0 + a13*y1, y3 - y0 + a23*y3, y0, - a13, a23, 1.0f); - } - } - - public static PerspectiveTransform quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) - { - // Here, the adjoint serves as the inverse: - return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint(); - } - - internal PerspectiveTransform buildAdjoint() - { - // Adjoint is the transpose of the cofactor matrix: - return new PerspectiveTransform(a22 * a33 - a23 * a32, - a23 * a31 - a21 * a33, - a21 * a32 - a22 * a31, - a13 * a32 - a12 * a33, - a11 * a33 - a13 * a31, - a12 * a31 - a11 * a32, - a12 * a23 - a13 * a22, - a13 * a21 - a11 * a23, - a11 * a22 - a12 * a21); - } - - internal PerspectiveTransform times(PerspectiveTransform other) - { - return new PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13, - a11 * other.a21 + a21 * other.a22 + a31 * other.a23, - a11 * other.a31 + a21 * other.a32 + a31 * other.a33, - a12 * other.a11 + a22 * other.a12 + a32 * other.a13, - a12 * other.a21 + a22 * other.a22 + a32 * other.a23, - a12 * other.a31 + a22 * other.a32 + a32 * other.a33, - a13 * other.a11 + a23 * other.a12 + a33 * other.a13, - a13 * other.a21 + a23 * other.a22 + a33 * other.a23, - a13 * other.a31 + a23 * other.a32 + a33 * other.a33); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/StringUtils.cs b/zxing.core/xx/common/StringUtils.cs deleted file mode 100644 index 6da8c55..0000000 --- a/zxing.core/xx/common/StringUtils.cs +++ /dev/null @@ -1,262 +0,0 @@ -/* - * 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 -{ - /// - /// Common string-related functions. - /// - /// Sean Owen - /// Alex Dupre - public static class StringUtils - { - private const String PLATFORM_DEFAULT_ENCODING = "UTF-8"; - 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; - - /// - /// Guesses the encoding. - /// - /// bytes encoding a string, whose encoding should be guessed - /// decode hints if applicable - /// 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 - public static String guessEncoding(byte[] bytes, IDictionary 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; - } - } -} diff --git a/zxing.core/xx/common/detector/MathUtils.cs b/zxing.core/xx/common/detector/MathUtils.cs deleted file mode 100644 index 2cd06e2..0000000 --- a/zxing.core/xx/common/detector/MathUtils.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.Common.Detector -{ - public static class MathUtils - { - /// - /// Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its - /// argument to the nearest int, where x.5 rounds up to x+1. Semantics of this shortcut - /// differ slightly from {@link Math#round(float)} in that half rounds down for negative - /// values. -2.5 rounds to -3, not -2. For purposes here it makes no difference. - /// - /// real value to round - /// nearest int - public static int round(float d) - { - if (float.IsNaN(d)) - return 0; - if (float.IsPositiveInfinity(d)) - return int.MaxValue; - return (int)(d + (d < 0.0f ? -0.5f : 0.5f)); - } - - public static float distance(float aX, float aY, float bX, float bY) - { - float xDiff = aX - bX; - float yDiff = aY - bY; - return (float)Math.Sqrt(xDiff * xDiff + yDiff * yDiff); - } - - public static float distance(int aX, int aY, int bX, int bY) - { - int xDiff = aX - bX; - int yDiff = aY - bY; - return (float)Math.Sqrt(xDiff * xDiff + yDiff * yDiff); - } - } -} diff --git a/zxing.core/xx/common/detector/MonochromeRectangleDetector.cs b/zxing.core/xx/common/detector/MonochromeRectangleDetector.cs deleted file mode 100644 index 3b0aeb3..0000000 --- a/zxing.core/xx/common/detector/MonochromeRectangleDetector.cs +++ /dev/null @@ -1,252 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.Common.Detector -{ - ///

A somewhat generic detector that looks for a barcode-like rectangular region within an image. - /// It looks within a mostly white region of an image for a region of black and white, but mostly - /// black. It returns the four corners of the region, as best it can determine.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public sealed class MonochromeRectangleDetector - { - private const int MAX_MODULES = 32; - - private BitMatrix image; - - public MonochromeRectangleDetector(BitMatrix image) - { - this.image = image; - } - - ///

Detects a rectangular region of black and white -- mostly black -- with a region of mostly - /// white, in an image.

- /// - ///
- /// {@link ResultPoint}[] describing the corners of the rectangular region. The first and - /// last points are opposed on the diagonal, as are the second and third. The first point will be - /// the topmost point and the last, the bottommost. The second point will be leftmost and the - /// third, the rightmost - /// - public ResultPoint[] detect() - { - int height = image.Height; - int width = image.Width; - int halfHeight = height >> 1; - int halfWidth = width >> 1; - int deltaY = System.Math.Max(1, height / (MAX_MODULES << 3)); - int deltaX = System.Math.Max(1, width / (MAX_MODULES << 3)); - - int top = 0; - int bottom = height; - int left = 0; - int right = width; - ResultPoint pointA = findCornerFromCenter(halfWidth, 0, left, right, halfHeight, -deltaY, top, bottom, halfWidth >> 1); - if (pointA == null) - return null; - top = (int)pointA.Y - 1; - ResultPoint pointB = findCornerFromCenter(halfWidth, -deltaX, left, right, halfHeight, 0, top, bottom, halfHeight >> 1); - if (pointB == null) - return null; - left = (int)pointB.X - 1; - ResultPoint pointC = findCornerFromCenter(halfWidth, deltaX, left, right, halfHeight, 0, top, bottom, halfHeight >> 1); - if (pointC == null) - return null; - right = (int)pointC.X + 1; - ResultPoint pointD = findCornerFromCenter(halfWidth, 0, left, right, halfHeight, deltaY, top, bottom, halfWidth >> 1); - if (pointD == null) - return null; - bottom = (int)pointD.Y + 1; - - // Go try to find point A again with better information -- might have been off at first. - pointA = findCornerFromCenter(halfWidth, 0, left, right, halfHeight, -deltaY, top, bottom, halfWidth >> 2); - if (pointA == null) - return null; - - return new ResultPoint[] { pointA, pointB, pointC, pointD }; - } - - /// Attempts to locate a corner of the barcode by scanning up, down, left or right from a center - /// point which should be within the barcode. - /// - /// - /// center's x component (horizontal) - /// - /// same as deltaY but change in x per step instead - /// - /// minimum value of x - /// - /// maximum value of x - /// - /// center's y component (vertical) - /// - /// change in y per step. If scanning up this is negative; down, positive; - /// left or right, 0 - /// - /// minimum value of y to search through (meaningless when di == 0) - /// - /// maximum value of y - /// - /// maximum run of white pixels that can still be considered to be within - /// the barcode - /// - /// a {@link com.google.zxing.ResultPoint} encapsulating the corner that was found - /// - private ResultPoint findCornerFromCenter(int centerX, int deltaX, int left, int right, int centerY, int deltaY, int top, int bottom, int maxWhiteRun) - { - int[] lastRange = null; - for (int y = centerY, x = centerX; y < bottom && y >= top && x < right && x >= left; y += deltaY, x += deltaX) - { - int[] range; - if (deltaX == 0) - { - // horizontal slices, up and down - range = blackWhiteRange(y, maxWhiteRun, left, right, true); - } - else - { - // vertical slices, left and right - range = blackWhiteRange(x, maxWhiteRun, top, bottom, false); - } - if (range == null) - { - if (lastRange == null) - { - return null; - } - // lastRange was found - if (deltaX == 0) - { - int lastY = y - deltaY; - if (lastRange[0] < centerX) - { - if (lastRange[1] > centerX) - { - // straddle, choose one or the other based on direction - return new ResultPoint(deltaY > 0 ? lastRange[0] : lastRange[1], lastY); - } - return new ResultPoint(lastRange[0], lastY); - } - else - { - return new ResultPoint(lastRange[1], lastY); - } - } - else - { - int lastX = x - deltaX; - if (lastRange[0] < centerY) - { - if (lastRange[1] > centerY) - { - return new ResultPoint(lastX, deltaX < 0 ? lastRange[0] : lastRange[1]); - } - return new ResultPoint(lastX, lastRange[0]); - } - else - { - return new ResultPoint(lastX, lastRange[1]); - } - } - } - lastRange = range; - } - return null; - } - - /// Computes the start and end of a region of pixels, either horizontally or vertically, that could - /// be part of a Data Matrix barcode. - /// - /// - /// if scanning horizontally, this is the row (the fixed vertical location) - /// where we are scanning. If scanning vertically it's the column, the fixed horizontal location - /// - /// largest run of white pixels that can still be considered part of the - /// barcode region - /// - /// minimum pixel location, horizontally or vertically, to consider - /// - /// maximum pixel location, horizontally or vertically, to consider - /// - /// if true, we're scanning left-right, instead of up-down - /// - /// int[] with start and end of found range, or null if no such range is found - /// (e.g. only white was found) - /// - private int[] blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim, bool horizontal) - { - int center = (minDim + maxDim) >> 1; - - // Scan left/up first - int start = center; - while (start >= minDim) - { - if (horizontal ? image[start, fixedDimension] : image[fixedDimension, start]) - { - start--; - } - else - { - int whiteRunStart = start; - do - { - start--; - } - while (start >= minDim && !(horizontal ? image[start, fixedDimension] : image[fixedDimension, start])); - int whiteRunSize = whiteRunStart - start; - if (start < minDim || whiteRunSize > maxWhiteRun) - { - start = whiteRunStart; - break; - } - } - } - start++; - - // Then try right/down - int end = center; - while (end < maxDim) - { - if (horizontal ? image[end, fixedDimension] : image[fixedDimension, end]) - { - end++; - } - else - { - int whiteRunStart = end; - do - { - end++; - } - while (end < maxDim && !(horizontal ? image[end, fixedDimension] : image[fixedDimension, end])); - int whiteRunSize = end - whiteRunStart; - if (end >= maxDim || whiteRunSize > maxWhiteRun) - { - end = whiteRunStart; - break; - } - } - } - end--; - - return end > start ? new int[] { start, end } : null; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/detector/WhiteRectangleDetector.cs b/zxing.core/xx/common/detector/WhiteRectangleDetector.cs deleted file mode 100644 index 0f7aefb..0000000 --- a/zxing.core/xx/common/detector/WhiteRectangleDetector.cs +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.Common.Detector -{ - /// - /// Detects a candidate barcode-like rectangular region within an image. It - /// starts around the center of the image, increases the size of the candidate - /// region until it finds a white rectangular region. By keeping track of the - /// last black points it encountered, it determines the corners of the barcode. - /// - /// David Olivier - public sealed class WhiteRectangleDetector - { - private const int INIT_SIZE = 10; - private const int CORR = 1; - - private readonly BitMatrix image; - private readonly int height; - private readonly int width; - private readonly int leftInit; - private readonly int rightInit; - private readonly int downInit; - private readonly int upInit; - - /// - /// Creates a WhiteRectangleDetector instance - /// - /// The image. - /// null, if image is too small, otherwise a WhiteRectangleDetector instance - public static WhiteRectangleDetector Create(BitMatrix image) - { - if (image == null) - return null; - - var instance = new WhiteRectangleDetector(image); - - if (instance.upInit < 0 || instance.leftInit < 0 || instance.downInit >= instance.height || instance.rightInit >= instance.width) - { - return null; - } - - return instance; - } - - /// - /// Creates a WhiteRectangleDetector instance - /// - /// barcode image to find a rectangle in - /// initial size of search area around center - /// x position of search center - /// y position of search center - /// - /// null, if image is too small, otherwise a WhiteRectangleDetector instance - /// - public static WhiteRectangleDetector Create(BitMatrix image, int initSize, int x, int y) - { - var instance = new WhiteRectangleDetector(image, initSize, x, y); - - if (instance.upInit < 0 || instance.leftInit < 0 || instance.downInit >= instance.height || instance.rightInit >= instance.width) - { - return null; - } - - return instance; - } - - - /// - /// Initializes a new instance of the class. - /// - /// The image. - /// if image is too small - internal WhiteRectangleDetector(BitMatrix image) - : this(image, INIT_SIZE, image.Width/2, image.Height/2) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The image. - /// Size of the init. - /// The x. - /// The y. - internal WhiteRectangleDetector(BitMatrix image, int initSize, int x, int y) - { - this.image = image; - height = image.Height; - width = image.Width; - int halfsize = initSize / 2; - leftInit = x - halfsize; - rightInit = x + halfsize; - upInit = y - halfsize; - downInit = y + halfsize; - } - - /// - /// Detects a candidate barcode-like rectangular region within an image. It - /// starts around the center of the image, increases the size of the candidate - /// region until it finds a white rectangular region. - /// - /// [] describing the corners of the rectangular - /// region. The first and last points are opposed on the diagonal, as - /// are the second and third. The first point will be the topmost - /// point and the last, the bottommost. The second point will be - /// leftmost and the third, the rightmost - public ResultPoint[] detect() - { - int left = leftInit; - int right = rightInit; - int up = upInit; - int down = downInit; - bool sizeExceeded = false; - bool aBlackPointFoundOnBorder = true; - bool atLeastOneBlackPointFoundOnBorder = false; - - bool atLeastOneBlackPointFoundOnRight = false; - bool atLeastOneBlackPointFoundOnBottom = false; - bool atLeastOneBlackPointFoundOnLeft = false; - bool atLeastOneBlackPointFoundOnTop = false; - - while (aBlackPointFoundOnBorder) - { - - aBlackPointFoundOnBorder = false; - - // ..... - // . | - // ..... - bool rightBorderNotWhite = true; - while ((rightBorderNotWhite || !atLeastOneBlackPointFoundOnRight) && right < width) - { - rightBorderNotWhite = containsBlackPoint(up, down, right, false); - if (rightBorderNotWhite) - { - right++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnRight = true; - } - else if (!atLeastOneBlackPointFoundOnRight) - { - right++; - } - } - - if (right >= width) - { - sizeExceeded = true; - break; - } - - // ..... - // . . - // .___. - bool bottomBorderNotWhite = true; - while ((bottomBorderNotWhite || !atLeastOneBlackPointFoundOnBottom) && down < height) - { - bottomBorderNotWhite = containsBlackPoint(left, right, down, true); - if (bottomBorderNotWhite) - { - down++; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnBottom = true; - } - else if (!atLeastOneBlackPointFoundOnBottom) - { - down++; - } - } - - if (down >= height) - { - sizeExceeded = true; - break; - } - - // ..... - // | . - // ..... - bool leftBorderNotWhite = true; - while ((leftBorderNotWhite || !atLeastOneBlackPointFoundOnLeft) && left >= 0) - { - leftBorderNotWhite = containsBlackPoint(up, down, left, false); - if (leftBorderNotWhite) - { - left--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnLeft = true; - } - else if (!atLeastOneBlackPointFoundOnLeft) - { - left--; - } - } - - if (left < 0) - { - sizeExceeded = true; - break; - } - - // .___. - // . . - // ..... - bool topBorderNotWhite = true; - while ((topBorderNotWhite || !atLeastOneBlackPointFoundOnTop) && up >= 0) - { - topBorderNotWhite = containsBlackPoint(left, right, up, true); - if (topBorderNotWhite) - { - up--; - aBlackPointFoundOnBorder = true; - atLeastOneBlackPointFoundOnTop = true; - } - else if (!atLeastOneBlackPointFoundOnTop) - { - up--; - } - } - - if (up < 0) - { - sizeExceeded = true; - break; - } - - if (aBlackPointFoundOnBorder) - { - atLeastOneBlackPointFoundOnBorder = true; - } - - } - - if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) - { - - int maxSize = right - left; - - ResultPoint z = null; - for (int i = 1; i < maxSize; i++) - { - z = getBlackPointOnSegment(left, down - i, left + i, down); - if (z != null) - { - break; - } - } - - if (z == null) - { - return null; - } - - ResultPoint t = null; - //go down right - for (int i = 1; i < maxSize; i++) - { - t = getBlackPointOnSegment(left, up + i, left + i, up); - if (t != null) - { - break; - } - } - - if (t == null) - { - return null; - } - - ResultPoint x = null; - //go down left - for (int i = 1; i < maxSize; i++) - { - x = getBlackPointOnSegment(right, up + i, right - i, up); - if (x != null) - { - break; - } - } - - if (x == null) - { - return null; - } - - ResultPoint y = null; - //go up left - for (int i = 1; i < maxSize; i++) - { - y = getBlackPointOnSegment(right, down - i, right - i, down); - if (y != null) - { - break; - } - } - - if (y == null) - { - return null; - } - - return centerEdges(y, z, x, t); - - } - else - { - return null; - } - } - - private ResultPoint getBlackPointOnSegment(float aX, float aY, float bX, float bY) - { - int dist = MathUtils.round(MathUtils.distance(aX, aY, bX, bY)); - float xStep = (bX - aX) / dist; - float yStep = (bY - aY) / dist; - - for (int i = 0; i < dist; i++) - { - int x = MathUtils.round(aX + i * xStep); - int y = MathUtils.round(aY + i * yStep); - if (image[x, y]) - { - return new ResultPoint(x, y); - } - } - return null; - } - - /// - /// recenters the points of a constant distance towards the center - /// - /// bottom most point - /// left most point - /// right most point - /// top most point - /// [] describing the corners of the rectangular - /// region. The first and last points are opposed on the diagonal, as - /// are the second and third. The first point will be the topmost - /// point and the last, the bottommost. The second point will be - /// leftmost and the third, the rightmost - private ResultPoint[] centerEdges(ResultPoint y, ResultPoint z, - ResultPoint x, ResultPoint t) - { - // - // t t - // z x - // x OR z - // y y - // - - float yi = y.X; - float yj = y.Y; - float zi = z.X; - float zj = z.Y; - float xi = x.X; - float xj = x.Y; - float ti = t.X; - float tj = t.Y; - - if (yi < width / 2.0f) - { - return new[] - { - new ResultPoint(ti - CORR, tj + CORR), - new ResultPoint(zi + CORR, zj + CORR), - new ResultPoint(xi - CORR, xj - CORR), - new ResultPoint(yi + CORR, yj - CORR) - }; - } - else - { - return new[] - { - new ResultPoint(ti + CORR, tj + CORR), - new ResultPoint(zi + CORR, zj - CORR), - new ResultPoint(xi - CORR, xj + CORR), - new ResultPoint(yi - CORR, yj - CORR) - }; - } - } - - /// - /// Determines whether a segment contains a black point - /// - /// min value of the scanned coordinate - /// max value of the scanned coordinate - /// value of fixed coordinate - /// set to true if scan must be horizontal, false if vertical - /// - /// true if a black point has been found, else false. - /// - private bool containsBlackPoint(int a, int b, int @fixed, bool horizontal) - { - if (horizontal) - { - for (int x = a; x <= b; x++) - { - if (image[x, @fixed]) - { - return true; - } - } - } - else - { - for (int y = a; y <= b; y++) - { - if (image[@fixed, y]) - { - return true; - } - } - } - return false; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/reedsolomon/GenericGF.cs b/zxing.core/xx/common/reedsolomon/GenericGF.cs deleted file mode 100644 index 58cdced..0000000 --- a/zxing.core/xx/common/reedsolomon/GenericGF.cs +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.Common.ReedSolomon -{ - /// - ///

This class contains utility methods for performing mathematical operations over - /// the Galois Fields. Operations use a given primitive polynomial in calculations.

- ///

Throughout this package, elements of the GF are represented as an {@code int} - /// for convenience and speed (but at the cost of memory). - ///

- ///
- /// Sean Owen - public sealed class GenericGF - { - public static GenericGF AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1 - public static GenericGF AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1 - public static GenericGF AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1 - public static GenericGF AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1 - public static GenericGF QR_CODE_FIELD_256 = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 - public static GenericGF DATA_MATRIX_FIELD_256 = new GenericGF(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1 - public static GenericGF AZTEC_DATA_8 = DATA_MATRIX_FIELD_256; - public static GenericGF MAXICODE_FIELD_64 = AZTEC_DATA_6; - - private int[] expTable; - private int[] logTable; - private GenericGFPoly zero; - private GenericGFPoly one; - private readonly int size; - private readonly int primitive; - private readonly int generatorBase; - - /// - /// Create a representation of GF(size) using the given primitive polynomial. - /// - /// irreducible polynomial whose coefficients are represented by - /// * the bits of an int, where the least-significant bit represents the constant - /// * coefficient - /// the size of the field - /// the factor b in the generator polynomial can be 0- or 1-based - /// * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))). - /// * In most cases it should be 1, but for QR code it is 0. - public GenericGF(int primitive, int size, int genBase) - { - this.primitive = primitive; - this.size = size; - this.generatorBase = genBase; - - expTable = new int[size]; - logTable = new int[size]; - int x = 1; - for (int i = 0; i < size; i++) - { - expTable[i] = x; - x <<= 1; // x = x * 2; we're assuming the generator alpha is 2 - if (x >= size) - { - x ^= primitive; - x &= size - 1; - } - } - for (int i = 0; i < size - 1; i++) - { - logTable[expTable[i]] = i; - } - // logTable[0] == 0 but this should never be used - zero = new GenericGFPoly(this, new int[] { 0 }); - one = new GenericGFPoly(this, new int[] { 1 }); - } - - internal GenericGFPoly Zero - { - get - { - return zero; - } - } - - internal GenericGFPoly One - { - get - { - return one; - } - } - - /// - /// Builds the monomial. - /// - /// The degree. - /// The coefficient. - /// the monomial representing coefficient * x^degree - internal GenericGFPoly buildMonomial(int degree, int coefficient) - { - if (degree < 0) - { - throw new ArgumentException(); - } - if (coefficient == 0) - { - return zero; - } - int[] coefficients = new int[degree + 1]; - coefficients[0] = coefficient; - return new GenericGFPoly(this, coefficients); - } - - /// - /// Implements both addition and subtraction -- they are the same in GF(size). - /// - /// sum/difference of a and b - static internal int addOrSubtract(int a, int b) - { - return a ^ b; - } - - /// - /// Exps the specified a. - /// - /// 2 to the power of a in GF(size) - internal int exp(int a) - { - return expTable[a]; - } - - /// - /// Logs the specified a. - /// - /// A. - /// base 2 log of a in GF(size) - internal int log(int a) - { - if (a == 0) - { - throw new ArgumentException(); - } - return logTable[a]; - } - - /// - /// Inverses the specified a. - /// - /// multiplicative inverse of a - internal int inverse(int a) - { - if (a == 0) - { - throw new ArithmeticException(); - } - return expTable[size - logTable[a] - 1]; - } - - /// - /// Multiplies the specified a with b. - /// - /// A. - /// The b. - /// product of a and b in GF(size) - internal int multiply(int a, int b) - { - if (a == 0 || b == 0) - { - return 0; - } - return expTable[(logTable[a] + logTable[b]) % (size - 1)]; - } - - /// - /// Gets the size. - /// - public int Size - { - get { return size; } - } - - /// - /// Gets the generator base. - /// - public int GeneratorBase - { - get { return generatorBase; } - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - override public String ToString() - { - return "GF(0x" + primitive.ToString("X") + ',' + size + ')'; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/reedsolomon/GenericGFPoly.cs b/zxing.core/xx/common/reedsolomon/GenericGFPoly.cs deleted file mode 100644 index 54ea8ad..0000000 --- a/zxing.core/xx/common/reedsolomon/GenericGFPoly.cs +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Text; - -namespace ZXing.Common.ReedSolomon -{ - /// - ///

Represents a polynomial whose coefficients are elements of a GF. - /// Instances of this class are immutable.

- ///

Much credit is due to William Rucklidge since portions of this code are an indirect - /// port of his C++ Reed-Solomon implementation.

- ///
- /// Sean Owen - internal sealed class GenericGFPoly - { - private readonly GenericGF field; - private readonly int[] coefficients; - - /// - /// Initializes a new instance of the class. - /// - /// the {@link GenericGF} instance representing the field to use - /// to perform computations - /// coefficients as ints representing elements of GF(size), arranged - /// from most significant (highest-power term) coefficient to least significant - /// if argument is null or empty, - /// or if leading coefficient is 0 and this is not a - /// constant polynomial (that is, it is not the monomial "0") - internal GenericGFPoly(GenericGF field, int[] coefficients) - { - if (coefficients.Length == 0) - { - throw new ArgumentException(); - } - this.field = field; - int coefficientsLength = coefficients.Length; - if (coefficientsLength > 1 && coefficients[0] == 0) - { - // Leading term must be non-zero for anything except the constant polynomial "0" - int firstNonZero = 1; - while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) - { - firstNonZero++; - } - if (firstNonZero == coefficientsLength) - { - this.coefficients = new int[]{0}; - } - else - { - this.coefficients = new int[coefficientsLength - firstNonZero]; - Array.Copy(coefficients, - firstNonZero, - this.coefficients, - 0, - this.coefficients.Length); - } - } - else - { - this.coefficients = coefficients; - } - } - - internal int[] Coefficients - { - get { return coefficients; } - } - - /// - /// degree of this polynomial - /// - internal int Degree - { - get - { - return coefficients.Length - 1; - } - } - - /// - /// Gets a value indicating whether this is zero. - /// - /// true iff this polynomial is the monomial "0" - internal bool isZero - { - get { return coefficients[0] == 0; } - } - - /// - /// coefficient of x^degree term in this polynomial - /// - /// The degree. - /// coefficient of x^degree term in this polynomial - internal int getCoefficient(int degree) - { - return coefficients[coefficients.Length - 1 - degree]; - } - - /// - /// evaluation of this polynomial at a given point - /// - /// A. - /// evaluation of this polynomial at a given point - internal int evaluateAt(int a) - { - int result = 0; - if (a == 0) - { - // Just return the x^0 coefficient - return getCoefficient(0); - } - int size = coefficients.Length; - if (a == 1) - { - // Just the sum of the coefficients - foreach (var coefficient in coefficients) - { - result = GenericGF.addOrSubtract(result, coefficient); - } - return result; - } - result = coefficients[0]; - for (int i = 1; i < size; i++) - { - result = GenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); - } - return result; - } - - internal GenericGFPoly addOrSubtract(GenericGFPoly other) - { - if (!field.Equals(other.field)) - { - throw new ArgumentException("GenericGFPolys do not have same GenericGF field"); - } - if (isZero) - { - return other; - } - if (other.isZero) - { - return this; - } - - int[] smallerCoefficients = this.coefficients; - int[] largerCoefficients = other.coefficients; - if (smallerCoefficients.Length > largerCoefficients.Length) - { - int[] temp = smallerCoefficients; - smallerCoefficients = largerCoefficients; - largerCoefficients = temp; - } - int[] sumDiff = new int[largerCoefficients.Length]; - int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length; - // Copy high-order terms only found in higher-degree polynomial's coefficients - Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff); - - for (int i = lengthDiff; i < largerCoefficients.Length; i++) - { - sumDiff[i] = GenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); - } - - return new GenericGFPoly(field, sumDiff); - } - - internal GenericGFPoly multiply(GenericGFPoly other) - { - if (!field.Equals(other.field)) - { - throw new ArgumentException("GenericGFPolys do not have same GenericGF field"); - } - if (isZero || other.isZero) - { - return field.Zero; - } - int[] aCoefficients = this.coefficients; - int aLength = aCoefficients.Length; - int[] bCoefficients = other.coefficients; - int bLength = bCoefficients.Length; - int[] product = new int[aLength + bLength - 1]; - for (int i = 0; i < aLength; i++) - { - int aCoeff = aCoefficients[i]; - for (int j = 0; j < bLength; j++) - { - product[i + j] = GenericGF.addOrSubtract(product[i + j], - field.multiply(aCoeff, bCoefficients[j])); - } - } - return new GenericGFPoly(field, product); - } - - internal GenericGFPoly multiply(int scalar) - { - if (scalar == 0) - { - return field.Zero; - } - if (scalar == 1) - { - return this; - } - int size = coefficients.Length; - int[] product = new int[size]; - for (int i = 0; i < size; i++) - { - product[i] = field.multiply(coefficients[i], scalar); - } - return new GenericGFPoly(field, product); - } - - internal GenericGFPoly multiplyByMonomial(int degree, int coefficient) - { - if (degree < 0) - { - throw new ArgumentException(); - } - if (coefficient == 0) - { - return field.Zero; - } - int size = coefficients.Length; - int[] product = new int[size + degree]; - for (int i = 0; i < size; i++) - { - product[i] = field.multiply(coefficients[i], coefficient); - } - return new GenericGFPoly(field, product); - } - - internal GenericGFPoly[] divide(GenericGFPoly other) - { - if (!field.Equals(other.field)) - { - throw new ArgumentException("GenericGFPolys do not have same GenericGF field"); - } - if (other.isZero) - { - throw new ArgumentException("Divide by 0"); - } - - GenericGFPoly quotient = field.Zero; - GenericGFPoly remainder = this; - - int denominatorLeadingTerm = other.getCoefficient(other.Degree); - int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); - - while (remainder.Degree >= other.Degree && !remainder.isZero) - { - int degreeDifference = remainder.Degree - other.Degree; - int scale = field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm); - GenericGFPoly term = other.multiplyByMonomial(degreeDifference, scale); - GenericGFPoly iterationQuotient = field.buildMonomial(degreeDifference, scale); - quotient = quotient.addOrSubtract(iterationQuotient); - remainder = remainder.addOrSubtract(term); - } - - return new GenericGFPoly[] { quotient, remainder }; - } - - public override String ToString() - { - StringBuilder result = new StringBuilder(8 * Degree); - for (int degree = Degree; degree >= 0; degree--) - { - int coefficient = getCoefficient(degree); - if (coefficient != 0) - { - if (coefficient < 0) - { - result.Append(" - "); - coefficient = -coefficient; - } - else - { - if (result.Length > 0) - { - result.Append(" + "); - } - } - if (degree == 0 || coefficient != 1) - { - int alphaPower = field.log(coefficient); - if (alphaPower == 0) - { - result.Append('1'); - } - else if (alphaPower == 1) - { - result.Append('a'); - } - else - { - result.Append("a^"); - result.Append(alphaPower); - } - } - if (degree != 0) - { - if (degree == 1) - { - result.Append('x'); - } - else - { - result.Append("x^"); - result.Append(degree); - } - } - } - } - return result.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/reedsolomon/ReedSolomonDecoder.cs b/zxing.core/xx/common/reedsolomon/ReedSolomonDecoder.cs deleted file mode 100644 index 9f97e0e..0000000 --- a/zxing.core/xx/common/reedsolomon/ReedSolomonDecoder.cs +++ /dev/null @@ -1,227 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.Common.ReedSolomon -{ - ///

Implements Reed-Solomon decoding, as the name implies.

- /// - ///

The algorithm will not be explained here, but the following references were helpful - /// in creating this implementation:

- /// - /// - /// - ///

Much credit is due to William Rucklidge since portions of this code are an indirect - /// port of his C++ Reed-Solomon implementation.

- /// - ///
- /// Sean Owen - /// William Rucklidge - /// sanfordsquires - public sealed class ReedSolomonDecoder - { - private readonly GenericGF field; - - public ReedSolomonDecoder(GenericGF field) - { - this.field = field; - } - - /// - ///

Decodes given set of received codewords, which include both data and error-correction - /// codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place, - /// in the input.

- ///
- /// data and error-correction codewords - /// number of error-correction codewords available - /// false: decoding fails - public bool decode(int[] received, int twoS) - { - var poly = new GenericGFPoly(field, received); - var syndromeCoefficients = new int[twoS]; - var noError = true; - for (var i = 0; i < twoS; i++) - { - var eval = poly.evaluateAt(field.exp(i + field.GeneratorBase)); - syndromeCoefficients[syndromeCoefficients.Length - 1 - i] = eval; - if (eval != 0) - { - noError = false; - } - } - if (noError) - { - return true; - } - var syndrome = new GenericGFPoly(field, syndromeCoefficients); - - var sigmaOmega = runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS); - if (sigmaOmega == null) - return false; - - var sigma = sigmaOmega[0]; - var errorLocations = findErrorLocations(sigma); - if (errorLocations == null) - return false; - - var omega = sigmaOmega[1]; - var errorMagnitudes = findErrorMagnitudes(omega, errorLocations); - for (var i = 0; i < errorLocations.Length; i++) - { - var position = received.Length - 1 - field.log(errorLocations[i]); - if (position < 0) - { - // throw new ReedSolomonException("Bad error location"); - return false; - } - received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]); - } - - return true; - } - - internal GenericGFPoly[] runEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R) - { - // Assume a's degree is >= b's - if (a.Degree < b.Degree) - { - GenericGFPoly temp = a; - a = b; - b = temp; - } - - GenericGFPoly rLast = a; - GenericGFPoly r = b; - GenericGFPoly tLast = field.Zero; - GenericGFPoly t = field.One; - - // Run Euclidean algorithm until r's degree is less than R/2 - while (r.Degree >= R / 2) - { - GenericGFPoly rLastLast = rLast; - GenericGFPoly tLastLast = tLast; - rLast = r; - tLast = t; - - // Divide rLastLast by rLast, with quotient in q and remainder in r - if (rLast.isZero) - { - // Oops, Euclidean algorithm already terminated? - // throw new ReedSolomonException("r_{i-1} was zero"); - return null; - } - r = rLastLast; - GenericGFPoly q = field.Zero; - int denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree); - int dltInverse = field.inverse(denominatorLeadingTerm); - while (r.Degree >= rLast.Degree && !r.isZero) - { - int degreeDiff = r.Degree - rLast.Degree; - int scale = field.multiply(r.getCoefficient(r.Degree), dltInverse); - q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale)); - r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale)); - } - - t = q.multiply(tLast).addOrSubtract(tLastLast); - - if (r.Degree >= rLast.Degree) - { - // throw new IllegalStateException("Division algorithm failed to reduce polynomial?"); - return null; - } - } - - int sigmaTildeAtZero = t.getCoefficient(0); - if (sigmaTildeAtZero == 0) - { - // throw new ReedSolomonException("sigmaTilde(0) was zero"); - return null; - } - - int inverse = field.inverse(sigmaTildeAtZero); - GenericGFPoly sigma = t.multiply(inverse); - GenericGFPoly omega = r.multiply(inverse); - return new GenericGFPoly[] { sigma, omega }; - } - - private int[] findErrorLocations(GenericGFPoly errorLocator) - { - // This is a direct application of Chien's search - int numErrors = errorLocator.Degree; - if (numErrors == 1) - { - // shortcut - return new int[] { errorLocator.getCoefficient(1) }; - } - int[] result = new int[numErrors]; - int e = 0; - for (int i = 1; i < field.Size && e < numErrors; i++) - { - if (errorLocator.evaluateAt(i) == 0) - { - result[e] = field.inverse(i); - e++; - } - } - if (e != numErrors) - { - // throw new ReedSolomonException("Error locator degree does not match number of roots"); - return null; - } - return result; - } - - private int[] findErrorMagnitudes(GenericGFPoly errorEvaluator, int[] errorLocations) - { - // This is directly applying Forney's Formula - int s = errorLocations.Length; - int[] result = new int[s]; - for (int i = 0; i < s; i++) - { - int xiInverse = field.inverse(errorLocations[i]); - int denominator = 1; - for (int j = 0; j < s; j++) - { - if (i != j) - { - //denominator = field.multiply(denominator, - // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); - // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug. - // Below is a funny-looking workaround from Steven Parkes - int term = field.multiply(errorLocations[j], xiInverse); - int termPlus1 = (term & 0x1) == 0 ? term | 1 : term & ~1; - denominator = field.multiply(denominator, termPlus1); - - // removed in java version, not sure if this is right - // denominator = field.multiply(denominator, GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse))); - } - } - result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator)); - if (field.GeneratorBase != 0) - { - result[i] = field.multiply(result[i], xiInverse); - } - } - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/common/reedsolomon/ReedSolomonEncoder.cs b/zxing.core/xx/common/reedsolomon/ReedSolomonEncoder.cs deleted file mode 100644 index d37a363..0000000 --- a/zxing.core/xx/common/reedsolomon/ReedSolomonEncoder.cs +++ /dev/null @@ -1,84 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -namespace ZXing.Common.ReedSolomon -{ - /// - /// Implements Reed-Solomon encoding, as the name implies. - /// - /// Sean Owen - /// William Rucklidge - public sealed class ReedSolomonEncoder - { - private readonly GenericGF field; - private readonly IList cachedGenerators; - - public ReedSolomonEncoder(GenericGF field) - { - this.field = field; - this.cachedGenerators = new List(); - cachedGenerators.Add(new GenericGFPoly(field, new int[] { 1 })); - } - - private GenericGFPoly buildGenerator(int degree) - { - if (degree >= cachedGenerators.Count) - { - var lastGenerator = cachedGenerators[cachedGenerators.Count - 1]; - for (int d = cachedGenerators.Count; d <= degree; d++) - { - var nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, new int[] { 1, field.exp(d - 1 + field.GeneratorBase) })); - cachedGenerators.Add(nextGenerator); - lastGenerator = nextGenerator; - } - } - return cachedGenerators[degree]; - } - - public void encode(int[] toEncode, int ecBytes) - { - if (ecBytes == 0) - { - throw new ArgumentException("No error correction bytes"); - } - var dataBytes = toEncode.Length - ecBytes; - if (dataBytes <= 0) - { - throw new ArgumentException("No data bytes provided"); - } - - var generator = buildGenerator(ecBytes); - var infoCoefficients = new int[dataBytes]; - Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes); - - var info = new GenericGFPoly(field, infoCoefficients); - info = info.multiplyByMonomial(ecBytes, 1); - - var remainder = info.divide(generator)[1]; - var coefficients = remainder.Coefficients; - var numZeroCoefficients = ecBytes - coefficients.Length; - for (var i = 0; i < numZeroCoefficients; i++) - { - toEncode[dataBytes + i] = 0; - } - - Array.Copy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.Length); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/DataMatrixReader.cs b/zxing.core/xx/datamatrix/DataMatrixReader.cs deleted file mode 100644 index b356937..0000000 --- a/zxing.core/xx/datamatrix/DataMatrixReader.cs +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Datamatrix.Internal; - -namespace ZXing.Datamatrix -{ - /// - /// This implementation can detect and decode Data Matrix codes in an image. - /// - /// bbrown@google.com (Brian Brown) - /// - public sealed class DataMatrixReader : Reader - { - private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0]; - - private readonly Decoder decoder = new Decoder(); - - /// - /// Locates and decodes a Data Matrix code in an image. - /// - /// a String representing the content encoded by the Data Matrix code - /// if a Data Matrix code cannot be decoded - /// - public Result decode(BinaryBitmap image) - { - return decode(image, null); - } - - public Result decode(BinaryBitmap image, IDictionary hints) - { - DecoderResult decoderResult; - ResultPoint[] points; - if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) - { - BitMatrix bits = extractPureBits(image.BlackMatrix); - if (bits == null) - return null; - decoderResult = decoder.decode(bits); - points = NO_POINTS; - } - else - { - DetectorResult detectorResult = new Detector(image.BlackMatrix).detect(); - if (detectorResult == null) - return null; - decoderResult = decoder.decode(detectorResult.Bits); - points = detectorResult.Points; - } - if (decoderResult == null) - return null; - - Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, - BarcodeFormat.DATA_MATRIX); - IList byteSegments = decoderResult.ByteSegments; - if (byteSegments != null) - { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - var ecLevel = decoderResult.ECLevel; - if (ecLevel != null) - { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - return result; - } - - public void reset() - { - // do nothing - } - - /// - /// This method detects a code in a "pure" image -- that is, pure monochrome image - /// which contains only an unrotated, unskewed, image of a code, with some white border - /// around it. This is a specialized method that works exceptionally fast in this special - /// case. - /// - /// - /// - private static BitMatrix extractPureBits(BitMatrix image) - { - int[] leftTopBlack = image.getTopLeftOnBit(); - int[] rightBottomBlack = image.getBottomRightOnBit(); - if (leftTopBlack == null || rightBottomBlack == null) - { - return null; - } - - int moduleSize; - if (!DataMatrixReader.moduleSize(leftTopBlack, image, out moduleSize)) - return null; - - int top = leftTopBlack[1]; - int bottom = rightBottomBlack[1]; - int left = leftTopBlack[0]; - int right = rightBottomBlack[0]; - - int matrixWidth = (right - left + 1) / moduleSize; - int matrixHeight = (bottom - top + 1) / moduleSize; - if (matrixWidth <= 0 || matrixHeight <= 0) - { - return null; - } - - // Push in the "border" by half the module width so that we start - // sampling in the middle of the module. Just in case the image is a - // little off, this will help recover. - int nudge = moduleSize >> 1; - top += nudge; - left += nudge; - - // Now just read off the bits - BitMatrix bits = new BitMatrix(matrixWidth, matrixHeight); - for (int y = 0; y < matrixHeight; y++) - { - int iOffset = top + y * moduleSize; - for (int x = 0; x < matrixWidth; x++) - { - if (image[left + x * moduleSize, iOffset]) - { - bits[x, y] = true; - } - } - } - return bits; - } - - private static bool moduleSize(int[] leftTopBlack, BitMatrix image, out int modulesize) - { - int width = image.Width; - int x = leftTopBlack[0]; - int y = leftTopBlack[1]; - while (x < width && image[x, y]) - { - x++; - } - if (x == width) - { - modulesize = 0; - return false; - } - - modulesize = x - leftTopBlack[0]; - if (modulesize == 0) - { - return false; - } - return true; - } - } -} diff --git a/zxing.core/xx/datamatrix/DataMatrixWriter.cs b/zxing.core/xx/datamatrix/DataMatrixWriter.cs deleted file mode 100644 index 9f0df71..0000000 --- a/zxing.core/xx/datamatrix/DataMatrixWriter.cs +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Datamatrix.Encoder; -using ZXing.QrCode.Internal; - -namespace ZXing.Datamatrix -{ - /// - /// This object renders a Data Matrix code as a BitMatrix 2D array of greyscale values. - /// - /// dswitkin@google.com (Daniel Switkin) - /// Guillaume Le Biller Added to zxing lib. - public sealed class DataMatrixWriter : Writer - { - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - { - return encode(contents, format, width, height, null); - } - - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, IDictionary hints) - { - if (String.IsNullOrEmpty(contents)) - { - throw new ArgumentException("Found empty contents", contents); - } - - if (format != BarcodeFormat.DATA_MATRIX) - { - throw new ArgumentException("Can only encode DATA_MATRIX, but got " + format); - } - - if (width < 0 || height < 0) - { - throw new ArgumentException("Requested dimensions are too small: " + width + 'x' + height); - } - - // Try to get force shape & min / max size - var shape = SymbolShapeHint.FORCE_NONE; - var defaultEncodation = Encodation.ASCII; - var minSize = new Dimension(width, height); - Dimension maxSize = null; - if (hints != null) - { - var requestedShape = hints.ContainsKey(EncodeHintType.DATA_MATRIX_SHAPE) ? (SymbolShapeHint?)hints[EncodeHintType.DATA_MATRIX_SHAPE] : null; - if (requestedShape != null) - { - shape = requestedShape.Value; - } - var requestedMinSize = hints.ContainsKey(EncodeHintType.MIN_SIZE) ? (Dimension)hints[EncodeHintType.MIN_SIZE] : null; - if (requestedMinSize != null) - { - minSize = requestedMinSize; - } - var requestedMaxSize = hints.ContainsKey(EncodeHintType.MAX_SIZE) ? (Dimension)hints[EncodeHintType.MAX_SIZE] : null; - if (requestedMaxSize != null) - { - maxSize = requestedMaxSize; - } - var requestedDefaultEncodation = hints.ContainsKey(EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION) ? (int?)hints[EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION] : (int?)null; - if (requestedDefaultEncodation != null) - { - defaultEncodation = requestedDefaultEncodation.Value; - } - } - - - //1. step: Data encodation - String encoded = HighLevelEncoder.encodeHighLevel(contents, shape, minSize, maxSize, defaultEncodation); - - SymbolInfo symbolInfo = SymbolInfo.lookup(encoded.Length, shape, minSize, maxSize, true); - - //2. step: ECC generation - String codewords = ErrorCorrection.encodeECC200(encoded, symbolInfo); - - //3. step: Module placement in Matrix - var placement = - new DefaultPlacement(codewords, symbolInfo.getSymbolDataWidth(), symbolInfo.getSymbolDataHeight()); - placement.place(); - - //4. step: low-level encoding - return encodeLowLevel(placement, symbolInfo); - } - - /// - /// Encode the given symbol info to a bit matrix. - /// - /// The DataMatrix placement. - /// The symbol info to encode. - /// The bit matrix generated. - private static BitMatrix encodeLowLevel(DefaultPlacement placement, SymbolInfo symbolInfo) - { - int symbolWidth = symbolInfo.getSymbolDataWidth(); - int symbolHeight = symbolInfo.getSymbolDataHeight(); - - var matrix = new ByteMatrix(symbolInfo.getSymbolWidth(), symbolInfo.getSymbolHeight()); - - int matrixY = 0; - - for (int y = 0; y < symbolHeight; y++) - { - // Fill the top edge with alternate 0 / 1 - int matrixX; - if ((y % symbolInfo.matrixHeight) == 0) - { - matrixX = 0; - for (int x = 0; x < symbolInfo.getSymbolWidth(); x++) - { - matrix.set(matrixX, matrixY, (x % 2) == 0); - matrixX++; - } - matrixY++; - } - matrixX = 0; - for (int x = 0; x < symbolWidth; x++) - { - // Fill the right edge with full 1 - if ((x % symbolInfo.matrixWidth) == 0) - { - matrix.set(matrixX, matrixY, true); - matrixX++; - } - matrix.set(matrixX, matrixY, placement.getBit(x, y)); - matrixX++; - // Fill the right edge with alternate 0 / 1 - if ((x % symbolInfo.matrixWidth) == symbolInfo.matrixWidth - 1) - { - matrix.set(matrixX, matrixY, (y % 2) == 0); - matrixX++; - } - } - matrixY++; - // Fill the bottom edge with full 1 - if ((y % symbolInfo.matrixHeight) == symbolInfo.matrixHeight - 1) - { - matrixX = 0; - for (int x = 0; x < symbolInfo.getSymbolWidth(); x++) - { - matrix.set(matrixX, matrixY, true); - matrixX++; - } - matrixY++; - } - } - - return convertByteMatrixToBitMatrix(matrix); - } - - /// - /// Convert the ByteMatrix to BitMatrix. - /// - /// The input matrix. - /// The output matrix. - private static BitMatrix convertByteMatrixToBitMatrix(ByteMatrix matrix) - { - int matrixWidgth = matrix.Width; - int matrixHeight = matrix.Height; - - var output = new BitMatrix(matrixWidgth, matrixHeight); - output.clear(); - for (int i = 0; i < matrixWidgth; i++) - { - for (int j = 0; j < matrixHeight; j++) - { - // Zero is white in the bytematrix - if (matrix[i, j] == 1) - { - output[i, j] = true; - } - } - } - - return output; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/decoder/BitMatrixParser.cs b/zxing.core/xx/datamatrix/decoder/BitMatrixParser.cs deleted file mode 100644 index ce5e496..0000000 --- a/zxing.core/xx/datamatrix/decoder/BitMatrixParser.cs +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -using ZXing.Common; - -namespace ZXing.Datamatrix.Internal -{ - /// - /// bbrown@google.com (Brian Brown) - /// - sealed class BitMatrixParser - { - private readonly BitMatrix mappingBitMatrix; - private readonly BitMatrix readMappingMatrix; - private readonly Version version; - - /// - /// to parse - /// if dimension is < 8 or >144 or not 0 mod 2 - /// - internal BitMatrixParser(BitMatrix bitMatrix) - { - int dimension = bitMatrix.Height; - if (dimension < 8 || dimension > 144 || (dimension & 0x01) != 0) - { - return; - } - - version = readVersion(bitMatrix); - if (version != null) - { - mappingBitMatrix = extractDataRegion(bitMatrix); - readMappingMatrix = new BitMatrix(mappingBitMatrix.Width, mappingBitMatrix.Height); - } - } - - public Version Version - { - get { return version; } - } - - /// - ///

Creates the version object based on the dimension of the original bit matrix from - /// the datamatrix code.

- /// - ///

See ISO 16022:2006 Table 7 - ECC 200 symbol attributes

- /// - /// Original including alignment patterns - /// encapsulating the Data Matrix Code's "version" - /// if the dimensions of the mapping matrix are not valid - /// Data Matrix dimensions. - ///
- internal static Version readVersion(BitMatrix bitMatrix) - { - int numRows = bitMatrix.Height; - int numColumns = bitMatrix.Width; - return Version.getVersionForDimensions(numRows, numColumns); - } - - /// - ///

Reads the bits in the representing the mapping matrix (No alignment patterns) - /// in the correct order in order to reconstitute the codewords bytes contained within the - /// Data Matrix Code.

- /// - /// bytes encoded within the Data Matrix Code - /// if the exact number of bytes expected is not read - ///
- internal byte[] readCodewords() - { - byte[] result = new byte[version.getTotalCodewords()]; - int resultOffset = 0; - - int row = 4; - int column = 0; - - int numRows = mappingBitMatrix.Height; - int numColumns = mappingBitMatrix.Width; - - bool corner1Read = false; - bool corner2Read = false; - bool corner3Read = false; - bool corner4Read = false; - - // Read all of the codewords - do - { - // Check the four corner cases - if ((row == numRows) && (column == 0) && !corner1Read) - { - result[resultOffset++] = (byte)readCorner1(numRows, numColumns); - row -= 2; - column += 2; - corner1Read = true; - } - else if ((row == numRows - 2) && (column == 0) && ((numColumns & 0x03) != 0) && !corner2Read) - { - result[resultOffset++] = (byte)readCorner2(numRows, numColumns); - row -= 2; - column += 2; - corner2Read = true; - } - else if ((row == numRows + 4) && (column == 2) && ((numColumns & 0x07) == 0) && !corner3Read) - { - result[resultOffset++] = (byte)readCorner3(numRows, numColumns); - row -= 2; - column += 2; - corner3Read = true; - } - else if ((row == numRows - 2) && (column == 0) && ((numColumns & 0x07) == 4) && !corner4Read) - { - result[resultOffset++] = (byte)readCorner4(numRows, numColumns); - row -= 2; - column += 2; - corner4Read = true; - } - else - { - // Sweep upward diagonally to the right - do - { - if ((row < numRows) && (column >= 0) && !readMappingMatrix[column, row]) - { - result[resultOffset++] = (byte)readUtah(row, column, numRows, numColumns); - } - row -= 2; - column += 2; - } while ((row >= 0) && (column < numColumns)); - row += 1; - column += 3; - - // Sweep downward diagonally to the left - do - { - if ((row >= 0) && (column < numColumns) && !readMappingMatrix[column, row]) - { - result[resultOffset++] = (byte)readUtah(row, column, numRows, numColumns); - } - row += 2; - column -= 2; - } while ((row < numRows) && (column >= 0)); - row += 3; - column += 1; - } - } while ((row < numRows) || (column < numColumns)); - - if (resultOffset != version.getTotalCodewords()) - { - return null; - } - return result; - } - - /// - ///

Reads a bit of the mapping matrix accounting for boundary wrapping.

- /// - /// Row to read in the mapping matrix - /// Column to read in the mapping matrix - /// Number of rows in the mapping matrix - /// Number of columns in the mapping matrix - /// value of the given bit in the mapping matrix - ///
- bool readModule(int row, int column, int numRows, int numColumns) - { - // Adjust the row and column indices based on boundary wrapping - if (row < 0) - { - row += numRows; - column += 4 - ((numRows + 4) & 0x07); - } - if (column < 0) - { - column += numColumns; - row += 4 - ((numColumns + 4) & 0x07); - } - readMappingMatrix[column, row] = true; - return mappingBitMatrix[column, row]; - } - - /// - ///

Reads the 8 bits of the standard Utah-shaped pattern.

- /// - ///

See ISO 16022:2006, 5.8.1 Figure 6

- /// - /// Current row in the mapping matrix, anchored at the 8th bit (LSB) of the pattern - /// Current column in the mapping matrix, anchored at the 8th bit (LSB) of the pattern - /// Number of rows in the mapping matrix - /// Number of columns in the mapping matrix - /// byte from the utah shape - ///
- int readUtah(int row, int column, int numRows, int numColumns) - { - int currentByte = 0; - if (readModule(row - 2, column - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 2, column - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 1, column - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 1, column - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row - 1, column, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row, column - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row, column - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(row, column, numRows, numColumns)) - { - currentByte |= 1; - } - return currentByte; - } - - /// - ///

Reads the 8 bits of the special corner condition 1.

- /// - ///

See ISO 16022:2006, Figure F.3

- /// - /// Number of rows in the mapping matrix - /// Number of columns in the mapping matrix - /// byte from the Corner condition 1 - ///
- int readCorner1(int numRows, int numColumns) - { - int currentByte = 0; - if (readModule(numRows - 1, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(2, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(3, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - return currentByte; - } - - /// - ///

Reads the 8 bits of the special corner condition 2.

- /// - ///

See ISO 16022:2006, Figure F.4

- /// - /// Number of rows in the mapping matrix - /// Number of columns in the mapping matrix - /// byte from the Corner condition 2 - ///
- int readCorner2(int numRows, int numColumns) - { - int currentByte = 0; - if (readModule(numRows - 3, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 2, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 4, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 3, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - return currentByte; - } - - /// - ///

Reads the 8 bits of the special corner condition 3.

- /// - ///

See ISO 16022:2006, Figure F.5

- /// - /// Number of rows in the mapping matrix - /// Number of columns in the mapping matrix - /// byte from the Corner condition 3 - ///
- int readCorner3(int numRows, int numColumns) - { - int currentByte = 0; - if (readModule(numRows - 1, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 3, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 3, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - return currentByte; - } - - /// - ///

Reads the 8 bits of the special corner condition 4.

- /// - ///

See ISO 16022:2006, Figure F.6

- /// - /// Number of rows in the mapping matrix - /// Number of columns in the mapping matrix - /// byte from the Corner condition 4 - ///
- int readCorner4(int numRows, int numColumns) - { - int currentByte = 0; - if (readModule(numRows - 3, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 2, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(numRows - 1, 0, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 2, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(0, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(1, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(2, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - currentByte <<= 1; - if (readModule(3, numColumns - 1, numRows, numColumns)) - { - currentByte |= 1; - } - return currentByte; - } - - /// - ///

Extracts the data region from a that contains - /// alignment patterns.

- /// - /// Original with alignment patterns - /// BitMatrix that has the alignment patterns removed - ///
- BitMatrix extractDataRegion(BitMatrix bitMatrix) - { - int symbolSizeRows = version.getSymbolSizeRows(); - int symbolSizeColumns = version.getSymbolSizeColumns(); - - if (bitMatrix.Height != symbolSizeRows) - { - throw new ArgumentException("Dimension of bitMarix must match the version size"); - } - - int dataRegionSizeRows = version.getDataRegionSizeRows(); - int dataRegionSizeColumns = version.getDataRegionSizeColumns(); - - int numDataRegionsRow = symbolSizeRows / dataRegionSizeRows; - int numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns; - - int sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows; - int sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns; - - BitMatrix bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow); - for (int dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) - { - int dataRegionRowOffset = dataRegionRow * dataRegionSizeRows; - for (int dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn) - { - int dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns; - for (int i = 0; i < dataRegionSizeRows; ++i) - { - int readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i; - int writeRowOffset = dataRegionRowOffset + i; - for (int j = 0; j < dataRegionSizeColumns; ++j) - { - int readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j; - if (bitMatrix[readColumnOffset, readRowOffset]) - { - int writeColumnOffset = dataRegionColumnOffset + j; - bitMatrixWithoutAlignment[writeColumnOffset, writeRowOffset] = true; - } - } - } - } - } - return bitMatrixWithoutAlignment; - } - - } -} diff --git a/zxing.core/xx/datamatrix/decoder/DataBlock.cs b/zxing.core/xx/datamatrix/decoder/DataBlock.cs deleted file mode 100644 index ce09b8d..0000000 --- a/zxing.core/xx/datamatrix/decoder/DataBlock.cs +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.Datamatrix.Internal -{ - /// - ///

Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into - /// multiple blocks, each of which is a unit of data and error-correction codewords. Each - /// is represented by an instance of this class.

- /// - /// bbrown@google.com (Brian Brown) - ///
- internal sealed class DataBlock - { - private readonly int numDataCodewords; - private readonly byte[] codewords; - - private DataBlock(int numDataCodewords, byte[] codewords) - { - this.numDataCodewords = numDataCodewords; - this.codewords = codewords; - } - - /// - ///

When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them. - /// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This - /// method will separate the data into original blocks.

- /// - /// bytes as read directly from the Data Matrix Code - /// version of the Data Matrix Code - /// DataBlocks containing original bytes, "de-interleaved" from representation in the - /// Data Matrix Code - ///
- internal static DataBlock[] getDataBlocks(byte[] rawCodewords, - Version version) - { - // Figure out the number and size of data blocks used by this version - Version.ECBlocks ecBlocks = version.getECBlocks(); - - // First count the total number of data blocks - int totalBlocks = 0; - Version.ECB[] ecBlockArray = ecBlocks.ECBlocksValue; - foreach (Version.ECB ecBlock in ecBlockArray) - { - totalBlocks += ecBlock.Count; - } - - // Now establish DataBlocks of the appropriate size and number of data codewords - DataBlock[] result = new DataBlock[totalBlocks]; - int numResultBlocks = 0; - foreach (Version.ECB ecBlock in ecBlockArray) - { - for (int i = 0; i < ecBlock.Count; i++) - { - int numDataCodewords = ecBlock.DataCodewords; - int numBlockCodewords = ecBlocks.ECCodewords + numDataCodewords; - result[numResultBlocks++] = new DataBlock(numDataCodewords, new byte[numBlockCodewords]); - } - } - - // All blocks have the same amount of data, except that the last n - // (where n may be 0) have 1 less byte. Figure out where these start. - // TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144 - int longerBlocksTotalCodewords = result[0].codewords.Length; - //int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1; - - int longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.ECCodewords; - int shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1; - // The last elements of result may be 1 element shorter for 144 matrix - // first fill out as many elements as all of them have minus 1 - int rawCodewordsOffset = 0; - for (int i = 0; i < shorterBlocksNumDataCodewords; i++) - { - for (int j = 0; j < numResultBlocks; j++) - { - result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; - } - } - - // Fill out the last data block in the longer ones - bool specialVersion = version.getVersionNumber() == 24; - int numLongerBlocks = specialVersion ? 8 : numResultBlocks; - for (int j = 0; j < numLongerBlocks; j++) - { - result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++]; - } - - // Now add in error correction blocks - int max = result[0].codewords.Length; - for (int i = longerBlocksNumDataCodewords; i < max; i++) - { - for (int j = 0; j < numResultBlocks; j++) - { - int jOffset = specialVersion ? (j + 8)%numResultBlocks : j; - int iOffset = specialVersion && jOffset > 7 ? i - 1 : i; - result[jOffset].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; - } - } - - if (rawCodewordsOffset != rawCodewords.Length) - { - throw new ArgumentException(); - } - - return result; - } - - internal int NumDataCodewords - { - get { return numDataCodewords; } - } - - internal byte[] Codewords - { - get { return codewords; } - } - } -} diff --git a/zxing.core/xx/datamatrix/decoder/DecodedBitStreamParser.cs b/zxing.core/xx/datamatrix/decoder/DecodedBitStreamParser.cs deleted file mode 100644 index badda6b..0000000 --- a/zxing.core/xx/datamatrix/decoder/DecodedBitStreamParser.cs +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using ZXing.Common; - -namespace ZXing.Datamatrix.Internal -{ - /// - ///

Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes - /// in one Data Matrix Code. This class decodes the bits back into text.

- /// - ///

See ISO 16022:2006, 5.2.1 - 5.2.9.2

- /// - /// bbrown@google.com (Brian Brown) - /// Sean Owen - ///
- internal static class DecodedBitStreamParser - { - private enum Mode - { - PAD_ENCODE, // Not really a mode - ASCII_ENCODE, - C40_ENCODE, - TEXT_ENCODE, - ANSIX12_ENCODE, - EDIFACT_ENCODE, - BASE256_ENCODE - } - - /// - /// See ISO 16022:2006, Annex C Table C.1 - /// The C40 Basic Character Set (*'s used for placeholders for the shift values) - /// - private static readonly char[] C40_BASIC_SET_CHARS = - { - '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' - }; - - private static readonly char[] C40_SHIFT2_SET_CHARS = - { - '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', - '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_' - }; - - /// - /// See ISO 16022:2006, Annex C Table C.2 - /// The Text Basic Character Set (*'s used for placeholders for the shift values) - /// - private static readonly char[] TEXT_BASIC_SET_CHARS = - { - '*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' - }; - - // Shift 2 for Text is the same encoding as C40 - private static readonly char[] TEXT_SHIFT2_SET_CHARS = C40_SHIFT2_SET_CHARS; - - private static readonly char[] TEXT_SHIFT3_SET_CHARS = - { - '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', - '|', '}', '~', (char) 127 - }; - - internal static DecoderResult decode(byte[] bytes) - { - BitSource bits = new BitSource(bytes); - StringBuilder result = new StringBuilder(100); - StringBuilder resultTrailer = new StringBuilder(0); - List byteSegments = new List(1); - Mode mode = Mode.ASCII_ENCODE; - do - { - if (mode == Mode.ASCII_ENCODE) - { - if (!decodeAsciiSegment(bits, result, resultTrailer, out mode)) - return null; - } - else - { - switch (mode) - { - case Mode.C40_ENCODE: - if (!decodeC40Segment(bits, result)) - return null; - break; - case Mode.TEXT_ENCODE: - if (!decodeTextSegment(bits, result)) - return null; - break; - case Mode.ANSIX12_ENCODE: - if (!decodeAnsiX12Segment(bits, result)) - return null; - break; - case Mode.EDIFACT_ENCODE: - if (!decodeEdifactSegment(bits, result)) - return null; - break; - case Mode.BASE256_ENCODE: - if (!decodeBase256Segment(bits, result, byteSegments)) - return null; - break; - default: - return null; - } - mode = Mode.ASCII_ENCODE; - } - } while (mode != Mode.PAD_ENCODE && bits.available() > 0); - if (resultTrailer.Length > 0) - { - result.Append(resultTrailer.ToString()); - } - return new DecoderResult(bytes, result.ToString(), byteSegments.Count == 0 ? null : byteSegments, null); - } - - /// - /// See ISO 16022:2006, 5.2.3 and Annex C, Table C.2 - /// - private static bool decodeAsciiSegment(BitSource bits, - StringBuilder result, - StringBuilder resultTrailer, - out Mode mode) - { - bool upperShift = false; - mode = Mode.ASCII_ENCODE; - do - { - int oneByte = bits.readBits(8); - if (oneByte == 0) - { - return false; - } - else if (oneByte <= 128) - { - // ASCII data (ASCII value + 1) - if (upperShift) - { - oneByte += 128; - //upperShift = false; - } - result.Append((char) (oneByte - 1)); - mode = Mode.ASCII_ENCODE; - return true; - } - else if (oneByte == 129) - { - // Pad - mode = Mode.PAD_ENCODE; - return true; - } - else if (oneByte <= 229) - { - // 2-digit data 00-99 (Numeric Value + 130) - int value = oneByte - 130; - if (value < 10) - { - // pad with '0' for single digit values - result.Append('0'); - } - result.Append(value); - } - else if (oneByte == 230) - { - // Latch to C40 encodation - mode = Mode.C40_ENCODE; - return true; - } - else if (oneByte == 231) - { - // Latch to Base 256 encodation - mode = Mode.BASE256_ENCODE; - return true; - } - else if (oneByte == 232) - { - // FNC1 - result.Append((char) 29); // translate as ASCII 29 - } - else if (oneByte == 233 || oneByte == 234) - { - // Structured Append, Reader Programming - // Ignore these symbols for now - //throw ReaderException.Instance; - } - else if (oneByte == 235) - { - // Upper Shift (shift to Extended ASCII) - upperShift = true; - } - else if (oneByte == 236) - { - // 05 Macro - result.Append("[)>\u001E05\u001D"); - resultTrailer.Insert(0, "\u001E\u0004"); - } - else if (oneByte == 237) - { - // 06 Macro - result.Append("[)>\u001E06\u001D"); - resultTrailer.Insert(0, "\u001E\u0004"); - } - else if (oneByte == 238) - { - // Latch to ANSI X12 encodation - mode = Mode.ANSIX12_ENCODE; - return true; - } - else if (oneByte == 239) - { - // Latch to Text encodation - mode = Mode.TEXT_ENCODE; - return true; - } - else if (oneByte == 240) - { - // Latch to EDIFACT encodation - mode = Mode.EDIFACT_ENCODE; - return true; - } - else if (oneByte == 241) - { - // ECI Character - // TODO(bbrown): I think we need to support ECI - //throw ReaderException.Instance; - // Ignore this symbol for now - } - else if (oneByte >= 242) - { - // Not to be used in ASCII encodation - // ... but work around encoders that end with 254, latch back to ASCII - if (oneByte != 254 || bits.available() != 0) - { - return false; - } - } - } while (bits.available() > 0); - mode = Mode.ASCII_ENCODE; - return true; - } - - /// - /// See ISO 16022:2006, 5.2.5 and Annex C, Table C.1 - /// - private static bool decodeC40Segment(BitSource bits, StringBuilder result) - { - // Three C40 values are encoded in a 16-bit value as - // (1600 * C1) + (40 * C2) + C3 + 1 - // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time - bool upperShift = false; - - int[] cValues = new int[3]; - int shift = 0; - - do - { - // If there is only one byte left then it will be encoded as ASCII - if (bits.available() == 8) - { - return true; - } - int firstByte = bits.readBits(8); - if (firstByte == 254) - { - // Unlatch codeword - return true; - } - - parseTwoBytes(firstByte, bits.readBits(8), cValues); - - for (int i = 0; i < 3; i++) - { - int cValue = cValues[i]; - switch (shift) - { - case 0: - if (cValue < 3) - { - shift = cValue + 1; - } - else if (cValue < C40_BASIC_SET_CHARS.Length) - { - char c40char = C40_BASIC_SET_CHARS[cValue]; - if (upperShift) - { - result.Append((char) (c40char + 128)); - upperShift = false; - } - else - { - result.Append(c40char); - } - } - else - { - return false; - } - break; - case 1: - if (upperShift) - { - result.Append((char) (cValue + 128)); - upperShift = false; - } - else - { - result.Append((char) cValue); - } - shift = 0; - break; - case 2: - if (cValue < C40_SHIFT2_SET_CHARS.Length) - { - char c40char = C40_SHIFT2_SET_CHARS[cValue]; - if (upperShift) - { - result.Append((char) (c40char + 128)); - upperShift = false; - } - else - { - result.Append(c40char); - } - } - else if (cValue == 27) - { - // FNC1 - result.Append((char) 29); // translate as ASCII 29 - } - else if (cValue == 30) - { - // Upper Shift - upperShift = true; - } - else - { - return false; - } - shift = 0; - break; - case 3: - if (upperShift) - { - result.Append((char) (cValue + 224)); - upperShift = false; - } - else - { - result.Append((char) (cValue + 96)); - } - shift = 0; - break; - default: - return false; - } - } - } while (bits.available() > 0); - - return true; - } - - /// - /// See ISO 16022:2006, 5.2.6 and Annex C, Table C.2 - /// - private static bool decodeTextSegment(BitSource bits, StringBuilder result) - { - // Three Text values are encoded in a 16-bit value as - // (1600 * C1) + (40 * C2) + C3 + 1 - // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time - bool upperShift = false; - - int[] cValues = new int[3]; - int shift = 0; - do - { - // If there is only one byte left then it will be encoded as ASCII - if (bits.available() == 8) - { - return true; - } - int firstByte = bits.readBits(8); - if (firstByte == 254) - { - // Unlatch codeword - return true; - } - - parseTwoBytes(firstByte, bits.readBits(8), cValues); - - for (int i = 0; i < 3; i++) - { - int cValue = cValues[i]; - switch (shift) - { - case 0: - if (cValue < 3) - { - shift = cValue + 1; - } - else if (cValue < TEXT_BASIC_SET_CHARS.Length) - { - char textChar = TEXT_BASIC_SET_CHARS[cValue]; - if (upperShift) - { - result.Append((char) (textChar + 128)); - upperShift = false; - } - else - { - result.Append(textChar); - } - } - else - { - return false; - } - break; - case 1: - if (upperShift) - { - result.Append((char) (cValue + 128)); - upperShift = false; - } - else - { - result.Append((char) cValue); - } - shift = 0; - break; - case 2: - // Shift 2 for Text is the same encoding as C40 - if (cValue < TEXT_SHIFT2_SET_CHARS.Length) - { - char textChar = TEXT_SHIFT2_SET_CHARS[cValue]; - if (upperShift) - { - result.Append((char) (textChar + 128)); - upperShift = false; - } - else - { - result.Append(textChar); - } - } - else if (cValue == 27) - { - // FNC1 - result.Append((char) 29); // translate as ASCII 29 - } - else if (cValue == 30) - { - // Upper Shift - upperShift = true; - } - else - { - return false; - } - shift = 0; - break; - case 3: - if (cValue < TEXT_SHIFT3_SET_CHARS.Length) - { - char textChar = TEXT_SHIFT3_SET_CHARS[cValue]; - if (upperShift) - { - result.Append((char) (textChar + 128)); - upperShift = false; - } - else - { - result.Append(textChar); - } - shift = 0; - } - else - { - return false; - } - break; - default: - return false; - } - } - } while (bits.available() > 0); - - return true; - } - - /// - /// See ISO 16022:2006, 5.2.7 - /// - private static bool decodeAnsiX12Segment(BitSource bits, - StringBuilder result) - { - // Three ANSI X12 values are encoded in a 16-bit value as - // (1600 * C1) + (40 * C2) + C3 + 1 - - int[] cValues = new int[3]; - do - { - // If there is only one byte left then it will be encoded as ASCII - if (bits.available() == 8) - { - return true; - } - int firstByte = bits.readBits(8); - if (firstByte == 254) - { - // Unlatch codeword - return true; - } - - parseTwoBytes(firstByte, bits.readBits(8), cValues); - - for (int i = 0; i < 3; i++) - { - int cValue = cValues[i]; - if (cValue == 0) - { - // X12 segment terminator - result.Append('\r'); - } - else if (cValue == 1) - { - // X12 segment separator * - result.Append('*'); - } - else if (cValue == 2) - { - // X12 sub-element separator > - result.Append('>'); - } - else if (cValue == 3) - { - // space - result.Append(' '); - } - else if (cValue < 14) - { - // 0 - 9 - result.Append((char) (cValue + 44)); - } - else if (cValue < 40) - { - // A - Z - result.Append((char) (cValue + 51)); - } - else - { - return false; - } - } - } while (bits.available() > 0); - - return true; - } - - private static void parseTwoBytes(int firstByte, int secondByte, int[] result) - { - int fullBitValue = (firstByte << 8) + secondByte - 1; - int temp = fullBitValue/1600; - result[0] = temp; - fullBitValue -= temp*1600; - temp = fullBitValue/40; - result[1] = temp; - result[2] = fullBitValue - temp*40; - } - - /// - /// See ISO 16022:2006, 5.2.8 and Annex C Table C.3 - /// - private static bool decodeEdifactSegment(BitSource bits, StringBuilder result) - { - do - { - // If there is only two or less bytes left then it will be encoded as ASCII - if (bits.available() <= 16) - { - return true; - } - - for (int i = 0; i < 4; i++) - { - int edifactValue = bits.readBits(6); - - // Check for the unlatch character - if (edifactValue == 0x1F) - { - // 011111 - // Read rest of byte, which should be 0, and stop - int bitsLeft = 8 - bits.BitOffset; - if (bitsLeft != 8) - { - bits.readBits(bitsLeft); - } - return true; - } - - if ((edifactValue & 0x20) == 0) - { - // no 1 in the leading (6th) bit - edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value - } - result.Append((char) edifactValue); - } - } while (bits.available() > 0); - - return true; - } - - /// - /// See ISO 16022:2006, 5.2.9 and Annex B, B.2 - /// - private static bool decodeBase256Segment(BitSource bits, - StringBuilder result, - IList byteSegments) - { - // Figure out how long the Base 256 Segment is. - int codewordPosition = 1 + bits.ByteOffset; // position is 1-indexed - int d1 = unrandomize255State(bits.readBits(8), codewordPosition++); - int count; - if (d1 == 0) - { - // Read the remainder of the symbol - count = bits.available()/8; - } - else if (d1 < 250) - { - count = d1; - } - else - { - count = 250*(d1 - 249) + unrandomize255State(bits.readBits(8), codewordPosition++); - } - - // We're seeing NegativeArraySizeException errors from users. - if (count < 0) - { - return false; - } - - byte[] bytes = new byte[count]; - for (int i = 0; i < count; i++) - { - // Have seen this particular error in the wild, such as at - // http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2 - if (bits.available() < 8) - { - return false; - } - bytes[i] = (byte) unrandomize255State(bits.readBits(8), codewordPosition++); - } - byteSegments.Add(bytes); - try - { -#if (WINDOWS_PHONE || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || WindowsCE || PORTABLE) -#if WindowsCE - result.Append(Encoding.GetEncoding(1252).GetString(bytes, 0, bytes.Length)); -#else - result.Append(Encoding.GetEncoding("ISO-8859-1").GetString(bytes, 0, bytes.Length)); -#endif -#else - result.Append(Encoding.GetEncoding("ISO-8859-1").GetString(bytes)); -#endif - } - catch (Exception uee) - { - throw new InvalidOperationException("Platform does not support required encoding: " + uee); - } - - return true; - } - - /// - /// See ISO 16022:2006, Annex B, B.2 - /// - private static int unrandomize255State(int randomizedBase256Codeword, - int base256CodewordPosition) - { - int pseudoRandomNumber = ((149*base256CodewordPosition)%255) + 1; - int tempVariable = randomizedBase256Codeword - pseudoRandomNumber; - return tempVariable >= 0 ? tempVariable : tempVariable + 256; - } - - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/decoder/Decoder.cs b/zxing.core/xx/datamatrix/decoder/Decoder.cs deleted file mode 100644 index dc75c98..0000000 --- a/zxing.core/xx/datamatrix/decoder/Decoder.cs +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using ZXing.Common; -using ZXing.Common.ReedSolomon; - -namespace ZXing.Datamatrix.Internal -{ - /// - ///

The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting - /// the Data Matrix Code from an image.

- /// - /// bbrown@google.com (Brian Brown) - ///
- public sealed class Decoder - { - private readonly ReedSolomonDecoder rsDecoder; - - /// - /// Initializes a new instance of the class. - /// - public Decoder() - { - rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256); - } - - /// - ///

Convenience method that can decode a Data Matrix Code represented as a 2D array of booleans. - /// "true" is taken to mean a black module.

- /// - /// booleans representing white/black Data Matrix Code modules - /// text and bytes encoded within the Data Matrix Code - /// if the Data Matrix Code cannot be decoded - /// if error correction fails - ///
- public DecoderResult decode(bool[][] image) - { - int dimension = image.Length; - BitMatrix bits = new BitMatrix(dimension); - for (int i = 0; i < dimension; i++) - { - for (int j = 0; j < dimension; j++) - { - if (image[i][j]) - { - bits[j, i] = true; - } - } - } - return decode(bits); - } - - /// - ///

Decodes a Data Matrix Code represented as a . A 1 or "true" is taken - /// to mean a black module.

- ///
- /// booleans representing white/black Data Matrix Code modules - /// text and bytes encoded within the Data Matrix Code - public DecoderResult decode(BitMatrix bits) - { - // Construct a parser and read version, error-correction level - BitMatrixParser parser = new BitMatrixParser(bits); - if (parser.Version == null) - return null; - - // Read codewords - byte[] codewords = parser.readCodewords(); - if (codewords == null) - return null; - // Separate into data blocks - DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, parser.Version); - - int dataBlocksCount = dataBlocks.Length; - - // Count total number of data bytes - int totalBytes = 0; - foreach (var db in dataBlocks) - { - totalBytes += db.NumDataCodewords; - } - byte[] resultBytes = new byte[totalBytes]; - - // Error-correct and copy data blocks together into a stream of bytes - for (int j = 0; j < dataBlocksCount; j++) - { - DataBlock dataBlock = dataBlocks[j]; - byte[] codewordBytes = dataBlock.Codewords; - int numDataCodewords = dataBlock.NumDataCodewords; - if (!correctErrors(codewordBytes, numDataCodewords)) - return null; - for (int i = 0; i < numDataCodewords; i++) - { - // De-interlace data blocks. - resultBytes[i * dataBlocksCount + j] = codewordBytes[i]; - } - } - - // Decode the contents of that stream of bytes - return DecodedBitStreamParser.decode(resultBytes); - } - - /// - ///

Given data and error-correction codewords received, possibly corrupted by errors, attempts to - /// correct the errors in-place using Reed-Solomon error correction.

- /// - /// data and error correction codewords - /// number of codewords that are data bytes - ///
- private bool correctErrors(byte[] codewordBytes, int numDataCodewords) - { - int numCodewords = codewordBytes.Length; - // First read into an array of ints - int[] codewordsInts = new int[numCodewords]; - for (int i = 0; i < numCodewords; i++) - { - codewordsInts[i] = codewordBytes[i] & 0xFF; - } - int numECCodewords = codewordBytes.Length - numDataCodewords; - if (!rsDecoder.decode(codewordsInts, numECCodewords)) - return false; - - // Copy back into array of bytes -- only need to worry about the bytes that were data - // We don't care about errors in the error-correction codewords - for (int i = 0; i < numDataCodewords; i++) - { - codewordBytes[i] = (byte)codewordsInts[i]; - } - - return true; - } - } -} diff --git a/zxing.core/xx/datamatrix/decoder/Version.cs b/zxing.core/xx/datamatrix/decoder/Version.cs deleted file mode 100644 index 6ec4e25..0000000 --- a/zxing.core/xx/datamatrix/decoder/Version.cs +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.Datamatrix.Internal -{ - /// - /// The Version object encapsulates attributes about a particular - /// size Data Matrix Code. - /// - /// bbrown@google.com (Brian Brown) - /// - public sealed class Version - { - private static readonly Version[] VERSIONS = buildVersions(); - - private readonly int versionNumber; - private readonly int symbolSizeRows; - private readonly int symbolSizeColumns; - private readonly int dataRegionSizeRows; - private readonly int dataRegionSizeColumns; - private readonly ECBlocks ecBlocks; - private readonly int totalCodewords; - - internal Version(int versionNumber, - int symbolSizeRows, - int symbolSizeColumns, - int dataRegionSizeRows, - int dataRegionSizeColumns, - ECBlocks ecBlocks) - { - this.versionNumber = versionNumber; - this.symbolSizeRows = symbolSizeRows; - this.symbolSizeColumns = symbolSizeColumns; - this.dataRegionSizeRows = dataRegionSizeRows; - this.dataRegionSizeColumns = dataRegionSizeColumns; - this.ecBlocks = ecBlocks; - - // Calculate the total number of codewords - int total = 0; - int ecCodewords = ecBlocks.ECCodewords; - ECB[] ecbArray = ecBlocks.ECBlocksValue; - foreach (ECB ecBlock in ecbArray) - { - total += ecBlock.Count * (ecBlock.DataCodewords + ecCodewords); - } - this.totalCodewords = total; - } - - public int getVersionNumber() - { - return versionNumber; - } - - public int getSymbolSizeRows() - { - return symbolSizeRows; - } - - public int getSymbolSizeColumns() - { - return symbolSizeColumns; - } - - public int getDataRegionSizeRows() - { - return dataRegionSizeRows; - } - - public int getDataRegionSizeColumns() - { - return dataRegionSizeColumns; - } - - public int getTotalCodewords() - { - return totalCodewords; - } - - internal ECBlocks getECBlocks() - { - return ecBlocks; - } - - /// - ///

Deduces version information from Data Matrix dimensions.

- /// - /// Number of rows in modules - /// Number of columns in modules - /// Version for a Data Matrix Code of those dimensions - /// if dimensions do correspond to a valid Data Matrix size - ///
- public static Version getVersionForDimensions(int numRows, int numColumns) - { - if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0) - { - return null; - } - - foreach (var version in VERSIONS) - { - if (version.symbolSizeRows == numRows && version.symbolSizeColumns == numColumns) - { - return version; - } - } - - return null; - } - - /// - ///

Encapsulates a set of error-correction blocks in one symbol version. Most versions will - /// use blocks of differing sizes within one version, so, this encapsulates the parameters for - /// each set of blocks. It also holds the number of error-correction codewords per block since it - /// will be the same across all blocks within one version.

- ///
- internal sealed class ECBlocks - { - private readonly int ecCodewords; - private readonly ECB[] _ecBlocksValue; - - internal ECBlocks(int ecCodewords, ECB ecBlocks) - { - this.ecCodewords = ecCodewords; - this._ecBlocksValue = new ECB[] { ecBlocks }; - } - - internal ECBlocks(int ecCodewords, ECB ecBlocks1, ECB ecBlocks2) - { - this.ecCodewords = ecCodewords; - this._ecBlocksValue = new ECB[] { ecBlocks1, ecBlocks2 }; - } - - internal int ECCodewords - { - get { return ecCodewords; } - } - - internal ECB[] ECBlocksValue - { - get { return _ecBlocksValue; } - } - } - - /// - ///

Encapsualtes the parameters for one error-correction block in one symbol version. - /// This includes the number of data codewords, and the number of times a block with these - /// parameters is used consecutively in the Data Matrix code version's format.

- ///
- internal sealed class ECB - { - private readonly int count; - private readonly int dataCodewords; - - internal ECB(int count, int dataCodewords) - { - this.count = count; - this.dataCodewords = dataCodewords; - } - - internal int Count - { - get { return count; } - } - - internal int DataCodewords - { - get { return dataCodewords; } - } - } - - override public String ToString() - { - return versionNumber.ToString(); - } - - /// - /// See ISO 16022:2006 5.5.1 Table 7 - /// - private static Version[] buildVersions() - { - return new Version[] - { - new Version(1, 10, 10, 8, 8, - new ECBlocks(5, new ECB(1, 3))), - new Version(2, 12, 12, 10, 10, - new ECBlocks(7, new ECB(1, 5))), - new Version(3, 14, 14, 12, 12, - new ECBlocks(10, new ECB(1, 8))), - new Version(4, 16, 16, 14, 14, - new ECBlocks(12, new ECB(1, 12))), - new Version(5, 18, 18, 16, 16, - new ECBlocks(14, new ECB(1, 18))), - new Version(6, 20, 20, 18, 18, - new ECBlocks(18, new ECB(1, 22))), - new Version(7, 22, 22, 20, 20, - new ECBlocks(20, new ECB(1, 30))), - new Version(8, 24, 24, 22, 22, - new ECBlocks(24, new ECB(1, 36))), - new Version(9, 26, 26, 24, 24, - new ECBlocks(28, new ECB(1, 44))), - new Version(10, 32, 32, 14, 14, - new ECBlocks(36, new ECB(1, 62))), - new Version(11, 36, 36, 16, 16, - new ECBlocks(42, new ECB(1, 86))), - new Version(12, 40, 40, 18, 18, - new ECBlocks(48, new ECB(1, 114))), - new Version(13, 44, 44, 20, 20, - new ECBlocks(56, new ECB(1, 144))), - new Version(14, 48, 48, 22, 22, - new ECBlocks(68, new ECB(1, 174))), - new Version(15, 52, 52, 24, 24, - new ECBlocks(42, new ECB(2, 102))), - new Version(16, 64, 64, 14, 14, - new ECBlocks(56, new ECB(2, 140))), - new Version(17, 72, 72, 16, 16, - new ECBlocks(36, new ECB(4, 92))), - new Version(18, 80, 80, 18, 18, - new ECBlocks(48, new ECB(4, 114))), - new Version(19, 88, 88, 20, 20, - new ECBlocks(56, new ECB(4, 144))), - new Version(20, 96, 96, 22, 22, - new ECBlocks(68, new ECB(4, 174))), - new Version(21, 104, 104, 24, 24, - new ECBlocks(56, new ECB(6, 136))), - new Version(22, 120, 120, 18, 18, - new ECBlocks(68, new ECB(6, 175))), - new Version(23, 132, 132, 20, 20, - new ECBlocks(62, new ECB(8, 163))), - new Version(24, 144, 144, 22, 22, - new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))), - new Version(25, 8, 18, 6, 16, - new ECBlocks(7, new ECB(1, 5))), - new Version(26, 8, 32, 6, 14, - new ECBlocks(11, new ECB(1, 10))), - new Version(27, 12, 26, 10, 24, - new ECBlocks(14, new ECB(1, 16))), - new Version(28, 12, 36, 10, 16, - new ECBlocks(18, new ECB(1, 22))), - new Version(29, 16, 36, 14, 16, - new ECBlocks(24, new ECB(1, 32))), - new Version(30, 16, 48, 14, 22, - new ECBlocks(28, new ECB(1, 49))) - }; - } - } -} diff --git a/zxing.core/xx/datamatrix/detector/Detector.cs b/zxing.core/xx/datamatrix/detector/Detector.cs deleted file mode 100644 index 23b5945..0000000 --- a/zxing.core/xx/datamatrix/detector/Detector.cs +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Common.Detector; - -namespace ZXing.Datamatrix.Internal -{ - /// - ///

Encapsulates logic that can detect a Data Matrix Code in an image, even if the Data Matrix Code - /// is rotated or skewed, or partially obscured.

- ///
- /// Sean Owen - public sealed class Detector - { - private readonly BitMatrix image; - private readonly WhiteRectangleDetector rectangleDetector; - - /// - /// Initializes a new instance of the class. - /// - /// The image. - public Detector(BitMatrix image) - { - this.image = image; - rectangleDetector = WhiteRectangleDetector.Create(image); - } - - /// - ///

Detects a Data Matrix Code in an image.

- ///
- /// encapsulating results of detecting a Data Matrix Code or null - public DetectorResult detect() - { - if (rectangleDetector == null) - // can be null, if the image is to small - return null; - ResultPoint[] cornerPoints = rectangleDetector.detect(); - if (cornerPoints == null) - return null; - var pointA = cornerPoints[0]; - var pointB = cornerPoints[1]; - var pointC = cornerPoints[2]; - var pointD = cornerPoints[3]; - - // Point A and D are across the diagonal from one another, - // as are B and C. Figure out which are the solid black lines - // by counting transitions - var transitions = new List(4); - transitions.Add(transitionsBetween(pointA, pointB)); - transitions.Add(transitionsBetween(pointA, pointC)); - transitions.Add(transitionsBetween(pointB, pointD)); - transitions.Add(transitionsBetween(pointC, pointD)); - transitions.Sort(new ResultPointsAndTransitionsComparator()); - - // Sort by number of transitions. First two will be the two solid sides; last two - // will be the two alternating black/white sides - var lSideOne = transitions[0]; - var lSideTwo = transitions[1]; - - // Figure out which point is their intersection by tallying up the number of times we see the - // endpoints in the four endpoints. One will show up twice. - var pointCount = new Dictionary(); - increment(pointCount, lSideOne.From); - increment(pointCount, lSideOne.To); - increment(pointCount, lSideTwo.From); - increment(pointCount, lSideTwo.To); - - ResultPoint maybeTopLeft = null; - ResultPoint bottomLeft = null; - ResultPoint maybeBottomRight = null; - foreach (var entry in pointCount) - { - ResultPoint point = entry.Key; - int value = entry.Value; - if (value == 2) - { - bottomLeft = point; // this is definitely the bottom left, then -- end of two L sides - } - else - { - // Otherwise it's either top left or bottom right -- just assign the two arbitrarily now - if (maybeTopLeft == null) - { - maybeTopLeft = point; - } - else - { - maybeBottomRight = point; - } - } - } - - if (maybeTopLeft == null || bottomLeft == null || maybeBottomRight == null) - { - return null; - } - - // Bottom left is correct but top left and bottom right might be switched - ResultPoint[] corners = { maybeTopLeft, bottomLeft, maybeBottomRight }; - // Use the dot product trick to sort them out - ResultPoint.orderBestPatterns(corners); - - // Now we know which is which: - ResultPoint bottomRight = corners[0]; - bottomLeft = corners[1]; - ResultPoint topLeft = corners[2]; - - // Which point didn't we find in relation to the "L" sides? that's the top right corner - ResultPoint topRight; - if (!pointCount.ContainsKey(pointA)) - { - topRight = pointA; - } - else if (!pointCount.ContainsKey(pointB)) - { - topRight = pointB; - } - else if (!pointCount.ContainsKey(pointC)) - { - topRight = pointC; - } - else - { - topRight = pointD; - } - - // Next determine the dimension by tracing along the top or right side and counting black/white - // transitions. Since we start inside a black module, we should see a number of transitions - // equal to 1 less than the code dimension. Well, actually 2 less, because we are going to - // end on a black module: - - // The top right point is actually the corner of a module, which is one of the two black modules - // adjacent to the white module at the top right. Tracing to that corner from either the top left - // or bottom right should work here. - - int dimensionTop = transitionsBetween(topLeft, topRight).Transitions; - int dimensionRight = transitionsBetween(bottomRight, topRight).Transitions; - - if ((dimensionTop & 0x01) == 1) - { - // it can't be odd, so, round... up? - dimensionTop++; - } - dimensionTop += 2; - - if ((dimensionRight & 0x01) == 1) - { - // it can't be odd, so, round... up? - dimensionRight++; - } - dimensionRight += 2; - - BitMatrix bits; - ResultPoint correctedTopRight; - - // Rectanguar symbols are 6x16, 6x28, 10x24, 10x32, 14x32, or 14x44. If one dimension is more - // than twice the other, it's certainly rectangular, but to cut a bit more slack we accept it as - // rectangular if the bigger side is at least 7/4 times the other: - if (4 * dimensionTop >= 7 * dimensionRight || 4 * dimensionRight >= 7 * dimensionTop) - { - // The matrix is rectangular - - correctedTopRight = - correctTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, dimensionTop, dimensionRight); - if (correctedTopRight == null) - { - correctedTopRight = topRight; - } - - dimensionTop = transitionsBetween(topLeft, correctedTopRight).Transitions; - dimensionRight = transitionsBetween(bottomRight, correctedTopRight).Transitions; - - if ((dimensionTop & 0x01) == 1) - { - // it can't be odd, so, round... up? - dimensionTop++; - } - - if ((dimensionRight & 0x01) == 1) - { - // it can't be odd, so, round... up? - dimensionRight++; - } - - bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionTop, dimensionRight); - } - else - { - // The matrix is square - - int dimension = Math.Min(dimensionRight, dimensionTop); - // correct top right point to match the white module - correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension); - if (correctedTopRight == null) - { - correctedTopRight = topRight; - } - - // Redetermine the dimension using the corrected top right point - int dimensionCorrected = Math.Max(transitionsBetween(topLeft, correctedTopRight).Transitions, - transitionsBetween(bottomRight, correctedTopRight).Transitions); - dimensionCorrected++; - if ((dimensionCorrected & 0x01) == 1) - { - dimensionCorrected++; - } - - bits = sampleGrid(image, - topLeft, - bottomLeft, - bottomRight, - correctedTopRight, - dimensionCorrected, - dimensionCorrected); - } - if (bits == null) - return null; - - return new DetectorResult(bits, new ResultPoint[] { topLeft, bottomLeft, bottomRight, correctedTopRight }); - } - - /// - /// Calculates the position of the white top right module using the output of the rectangle detector - /// for a rectangular matrix - /// - private ResultPoint correctTopRightRectangular(ResultPoint bottomLeft, - ResultPoint bottomRight, - ResultPoint topLeft, - ResultPoint topRight, - int dimensionTop, - int dimensionRight) - { - - float corr = distance(bottomLeft, bottomRight) / (float)dimensionTop; - int norm = distance(topLeft, topRight); - if (norm == 0) - return null; - float cos = (topRight.X - topLeft.X) / norm; - float sin = (topRight.Y - topLeft.Y) / norm; - - ResultPoint c1 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin); - - corr = distance(bottomLeft, topLeft) / (float)dimensionRight; - norm = distance(bottomRight, topRight); - if (norm == 0) - return null; - cos = (topRight.X - bottomRight.X) / norm; - sin = (topRight.Y - bottomRight.Y) / norm; - - ResultPoint c2 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin); - - if (!isValid(c1)) - { - if (isValid(c2)) - { - return c2; - } - return null; - } - if (!isValid(c2)) - { - return c1; - } - - int l1 = Math.Abs(dimensionTop - transitionsBetween(topLeft, c1).Transitions) + - Math.Abs(dimensionRight - transitionsBetween(bottomRight, c1).Transitions); - int l2 = Math.Abs(dimensionTop - transitionsBetween(topLeft, c2).Transitions) + - Math.Abs(dimensionRight - transitionsBetween(bottomRight, c2).Transitions); - - if (l1 <= l2) - { - return c1; - } - - return c2; - } - - /// - /// Calculates the position of the white top right module using the output of the rectangle detector - /// for a square matrix - /// - private ResultPoint correctTopRight(ResultPoint bottomLeft, - ResultPoint bottomRight, - ResultPoint topLeft, - ResultPoint topRight, - int dimension) - { - - float corr = distance(bottomLeft, bottomRight) / (float)dimension; - int norm = distance(topLeft, topRight); - if (norm == 0) - return null; - float cos = (topRight.X - topLeft.X) / norm; - float sin = (topRight.Y - topLeft.Y) / norm; - - ResultPoint c1 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin); - - corr = distance(bottomLeft, topLeft) / (float)dimension; - norm = distance(bottomRight, topRight); - if (norm == 0) - return null; - cos = (topRight.X - bottomRight.X) / norm; - sin = (topRight.Y - bottomRight.Y) / norm; - - ResultPoint c2 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin); - - if (!isValid(c1)) - { - if (isValid(c2)) - { - return c2; - } - return null; - } - if (!isValid(c2)) - { - return c1; - } - - int l1 = Math.Abs(transitionsBetween(topLeft, c1).Transitions - - transitionsBetween(bottomRight, c1).Transitions); - int l2 = Math.Abs(transitionsBetween(topLeft, c2).Transitions - - transitionsBetween(bottomRight, c2).Transitions); - - return l1 <= l2 ? c1 : c2; - } - - private bool isValid(ResultPoint p) - { - return p.X >= 0 && p.X < image.Width && p.Y > 0 && p.Y < image.Height; - } - - // L2 distance - private static int distance(ResultPoint a, ResultPoint b) - { - return MathUtils.round(ResultPoint.distance(a, b)); - } - - /// - /// Increments the Integer associated with a key by one. - /// - private static void increment(IDictionary table, ResultPoint key) - { - if (table.ContainsKey(key)) - { - int value = table[key]; - table[key] = value + 1; - } - else - { - table[key] = 1; - } - } - - private static BitMatrix sampleGrid(BitMatrix image, - ResultPoint topLeft, - ResultPoint bottomLeft, - ResultPoint bottomRight, - ResultPoint topRight, - int dimensionX, - int dimensionY) - { - - GridSampler sampler = GridSampler.Instance; - - return sampler.sampleGrid(image, - dimensionX, - dimensionY, - 0.5f, - 0.5f, - dimensionX - 0.5f, - 0.5f, - dimensionX - 0.5f, - dimensionY - 0.5f, - 0.5f, - dimensionY - 0.5f, - topLeft.X, - topLeft.Y, - topRight.X, - topRight.Y, - bottomRight.X, - bottomRight.Y, - bottomLeft.X, - bottomLeft.Y); - } - - /// - /// Counts the number of black/white transitions between two points, using something like Bresenham's algorithm. - /// - private ResultPointsAndTransitions transitionsBetween(ResultPoint from, ResultPoint to) - { - // See QR Code Detector, sizeOfBlackWhiteBlackRun() - int fromX = (int)from.X; - int fromY = (int)from.Y; - int toX = (int)to.X; - int toY = (int)to.Y; - bool steep = Math.Abs(toY - fromY) > Math.Abs(toX - fromX); - if (steep) - { - int temp = fromX; - fromX = fromY; - fromY = temp; - temp = toX; - toX = toY; - toY = temp; - } - - int dx = Math.Abs(toX - fromX); - int dy = Math.Abs(toY - fromY); - int error = -dx >> 1; - int ystep = fromY < toY ? 1 : -1; - int xstep = fromX < toX ? 1 : -1; - int transitions = 0; - bool inBlack = image[steep ? fromY : fromX, steep ? fromX : fromY]; - for (int x = fromX, y = fromY; x != toX; x += xstep) - { - bool isBlack = image[steep ? y : x, steep ? x : y]; - if (isBlack != inBlack) - { - transitions++; - inBlack = isBlack; - } - error += dy; - if (error > 0) - { - if (y == toY) - { - break; - } - y += ystep; - error -= dx; - } - } - return new ResultPointsAndTransitions(from, to, transitions); - } - - /// - /// Simply encapsulates two points and a number of transitions between them. - /// - private sealed class ResultPointsAndTransitions - { - public ResultPoint From { get; private set; } - public ResultPoint To { get; private set; } - public int Transitions { get; private set; } - - public ResultPointsAndTransitions(ResultPoint from, ResultPoint to, int transitions) - { - From = from; - To = to; - Transitions = transitions; - } - - override public String ToString() - { - return From + "/" + To + '/' + Transitions; - } - } - - /// - /// Orders ResultPointsAndTransitions by number of transitions, ascending. - /// - private sealed class ResultPointsAndTransitionsComparator : IComparer - { - public int Compare(ResultPointsAndTransitions o1, ResultPointsAndTransitions o2) - { - return o1.Transitions - o2.Transitions; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/ASCIIEncoder.cs b/zxing.core/xx/datamatrix/encoder/ASCIIEncoder.cs deleted file mode 100644 index 3cf1b81..0000000 --- a/zxing.core/xx/datamatrix/encoder/ASCIIEncoder.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * 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.Datamatrix.Encoder -{ - internal sealed class ASCIIEncoder : Encoder - { - public int EncodingMode - { - get { return Encodation.ASCII; } - } - - public void encode(EncoderContext context) - { - //step B - int n = HighLevelEncoder.determineConsecutiveDigitCount(context.Message, context.Pos); - if (n >= 2) - { - context.writeCodeword(encodeASCIIDigits(context.Message[context.Pos], - context.Message[context.Pos + 1])); - context.Pos += 2; - } - else - { - char c = context.CurrentChar; - int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode); - if (newMode != EncodingMode) - { - switch (newMode) - { - case Encodation.BASE256: - context.writeCodeword(HighLevelEncoder.LATCH_TO_BASE256); - context.signalEncoderChange(Encodation.BASE256); - return; - case Encodation.C40: - context.writeCodeword(HighLevelEncoder.LATCH_TO_C40); - context.signalEncoderChange(Encodation.C40); - return; - case Encodation.X12: - context.writeCodeword(HighLevelEncoder.LATCH_TO_ANSIX12); - context.signalEncoderChange(Encodation.X12); - break; - case Encodation.TEXT: - context.writeCodeword(HighLevelEncoder.LATCH_TO_TEXT); - context.signalEncoderChange(Encodation.TEXT); - break; - case Encodation.EDIFACT: - context.writeCodeword(HighLevelEncoder.LATCH_TO_EDIFACT); - context.signalEncoderChange(Encodation.EDIFACT); - break; - default: - throw new InvalidOperationException("Illegal mode: " + newMode); - } - } - else if (HighLevelEncoder.isExtendedASCII(c)) - { - context.writeCodeword(HighLevelEncoder.UPPER_SHIFT); - context.writeCodeword((char)(c - 128 + 1)); - context.Pos++; - } - else - { - context.writeCodeword((char)(c + 1)); - context.Pos++; - } - - } - } - - private static char encodeASCIIDigits(char digit1, char digit2) - { - if (HighLevelEncoder.isDigit(digit1) && HighLevelEncoder.isDigit(digit2)) - { - int num = (digit1 - 48) * 10 + (digit2 - 48); - return (char)(num + 130); - } - throw new ArgumentException("not digits: " + digit1 + digit2); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/Base256Encoder.cs b/zxing.core/xx/datamatrix/encoder/Base256Encoder.cs deleted file mode 100644 index 1cc5344..0000000 --- a/zxing.core/xx/datamatrix/encoder/Base256Encoder.cs +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * 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.Text; - -namespace ZXing.Datamatrix.Encoder -{ - internal sealed class Base256Encoder : Encoder - { - public int EncodingMode - { - get { return Encodation.BASE256; } - } - - public void encode(EncoderContext context) - { - var buffer = new StringBuilder(); - buffer.Append('\u0000'); //Initialize length field - while (context.HasMoreCharacters) - { - char c = context.CurrentChar; - buffer.Append(c); - - context.Pos++; - - int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode); - if (newMode != EncodingMode) - { - context.signalEncoderChange(newMode); - break; - } - } - int dataCount = buffer.Length - 1; - const int lengthFieldSize = 1; - int currentSize = context.CodewordCount + dataCount + lengthFieldSize; - context.updateSymbolInfo(currentSize); - bool mustPad = (context.SymbolInfo.dataCapacity - currentSize) > 0; - if (context.HasMoreCharacters || mustPad) - { - if (dataCount <= 249) - { - buffer[0] = (char)dataCount; - } - else if (dataCount > 249 && dataCount <= 1555) - { - buffer[0] = (char)((dataCount / 250) + 249); - buffer.Insert(1, new [] { (char)(dataCount % 250) }); - } - else - { - throw new InvalidOperationException( - "Message length not in valid ranges: " + dataCount); - } - } - { - var c = buffer.Length; - for (int i = 0; i < c; i++) - { - context.writeCodeword(randomize255State( - buffer[i], context.CodewordCount + 1)); - } - } - } - - private static char randomize255State(char ch, int codewordPosition) - { - int pseudoRandom = ((149 * codewordPosition) % 255) + 1; - int tempVariable = ch + pseudoRandom; - if (tempVariable <= 255) - { - return (char)tempVariable; - } - return (char)(tempVariable - 256); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/C40Encoder.cs b/zxing.core/xx/datamatrix/encoder/C40Encoder.cs deleted file mode 100644 index 3babd0f..0000000 --- a/zxing.core/xx/datamatrix/encoder/C40Encoder.cs +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * 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.Text; - -namespace ZXing.Datamatrix.Encoder -{ - internal class C40Encoder : Encoder - { - virtual public int EncodingMode - { - get { return Encodation.C40; } - } - - virtual public void encode(EncoderContext context) - { - //step C - var buffer = new StringBuilder(); - while (context.HasMoreCharacters) - { - char c = context.CurrentChar; - context.Pos++; - - int lastCharSize = encodeChar(c, buffer); - - int unwritten = (buffer.Length / 3) * 2; - - int curCodewordCount = context.CodewordCount + unwritten; - context.updateSymbolInfo(curCodewordCount); - int available = context.SymbolInfo.dataCapacity - curCodewordCount; - - if (!context.HasMoreCharacters) - { - //Avoid having a single C40 value in the last triplet - var removed = new StringBuilder(); - if ((buffer.Length % 3) == 2) - { - if (available < 2 || available > 2) - { - lastCharSize = backtrackOneCharacter(context, buffer, removed, - lastCharSize); - } - } - while ((buffer.Length % 3) == 1 - && ((lastCharSize <= 3 && available != 1) || lastCharSize > 3)) - { - lastCharSize = backtrackOneCharacter(context, buffer, removed, lastCharSize); - } - break; - } - - int count = buffer.Length; - if ((count % 3) == 0) - { - int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode); - if (newMode != EncodingMode) - { - context.signalEncoderChange(newMode); - break; - } - } - } - handleEOD(context, buffer); - } - - private int backtrackOneCharacter(EncoderContext context, - StringBuilder buffer, StringBuilder removed, int lastCharSize) - { - int count = buffer.Length; - buffer.Remove(count - lastCharSize, lastCharSize); - context.Pos--; - char c = context.CurrentChar; - lastCharSize = encodeChar(c, removed); - context.resetSymbolInfo(); //Deal with possible reduction in symbol size - return lastCharSize; - } - - internal static void writeNextTriplet(EncoderContext context, StringBuilder buffer) - { - context.writeCodewords(encodeToCodewords(buffer, 0)); - buffer.Remove(0, 3); - } - - /// - /// Handle "end of data" situations - /// - /// the encoder context - /// the buffer with the remaining encoded characters - virtual protected void handleEOD(EncoderContext context, StringBuilder buffer) - { - int unwritten = (buffer.Length / 3) * 2; - int rest = buffer.Length % 3; - - int curCodewordCount = context.CodewordCount + unwritten; - context.updateSymbolInfo(curCodewordCount); - int available = context.SymbolInfo.dataCapacity - curCodewordCount; - - if (rest == 2) - { - buffer.Append('\u0000'); //Shift 1 - while (buffer.Length >= 3) - { - writeNextTriplet(context, buffer); - } - if (context.HasMoreCharacters) - { - context.writeCodeword(HighLevelEncoder.C40_UNLATCH); - } - } - else if (available == 1 && rest == 1) - { - while (buffer.Length >= 3) - { - writeNextTriplet(context, buffer); - } - if (context.HasMoreCharacters) - { - context.writeCodeword(HighLevelEncoder.C40_UNLATCH); - } - // else no unlatch - context.Pos--; - } - else if (rest == 0) - { - while (buffer.Length >= 3) - { - writeNextTriplet(context, buffer); - } - if (available > 0 || context.HasMoreCharacters) - { - context.writeCodeword(HighLevelEncoder.C40_UNLATCH); - } - } - else - { - throw new InvalidOperationException("Unexpected case. Please report!"); - } - context.signalEncoderChange(Encodation.ASCII); - } - - virtual protected int encodeChar(char c, StringBuilder sb) - { - if (c == ' ') - { - sb.Append('\u0003'); - return 1; - } - if (c >= '0' && c <= '9') - { - sb.Append((char)(c - 48 + 4)); - return 1; - } - if (c >= 'A' && c <= 'Z') - { - sb.Append((char)(c - 65 + 14)); - return 1; - } - if (c >= '\u0000' && c <= '\u001f') - { - sb.Append('\u0000'); //Shift 1 Set - sb.Append(c); - return 2; - } - if (c >= '!' && c <= '/') - { - sb.Append('\u0001'); //Shift 2 Set - sb.Append((char)(c - 33)); - return 2; - } - if (c >= ':' && c <= '@') - { - sb.Append('\u0001'); //Shift 2 Set - sb.Append((char)(c - 58 + 15)); - return 2; - } - if (c >= '[' && c <= '_') - { - sb.Append('\u0001'); //Shift 2 Set - sb.Append((char)(c - 91 + 22)); - return 2; - } - if (c >= '\u0060' && c <= '\u007f') - { - sb.Append('\u0002'); //Shift 3 Set - sb.Append((char)(c - 96)); - return 2; - } - if (c >= '\u0080') - { - sb.Append("\u0001\u001e"); //Shift 2, Upper Shift - int len = 2; - len += encodeChar((char)(c - 128), sb); - return len; - } - throw new InvalidOperationException("Illegal character: " + c); - } - - private static String encodeToCodewords(StringBuilder sb, int startPos) - { - char c1 = sb[startPos]; - char c2 = sb[startPos + 1]; - char c3 = sb[startPos + 2]; - int v = (1600 * c1) + (40 * c2) + c3 + 1; - char cw1 = (char)(v / 256); - char cw2 = (char)(v % 256); - return new String(new char[] { cw1, cw2 }); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/DataMatrixSymbolInfo144.cs b/zxing.core/xx/datamatrix/encoder/DataMatrixSymbolInfo144.cs deleted file mode 100644 index 681e5b1..0000000 --- a/zxing.core/xx/datamatrix/encoder/DataMatrixSymbolInfo144.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki - * - * 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.Datamatrix.Encoder -{ - internal sealed class DataMatrixSymbolInfo144 : SymbolInfo - { - public DataMatrixSymbolInfo144() - : base(false, 1558, 620, 22, 22, 36, -1, 62) - { - } - - public override int getInterleavedBlockCount() - { - return 10; - } - - public override int getDataLengthForInterleavedBlock(int index) - { - return (index <= 8) ? 156 : 155; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/DatamatrixEncodingOptions.cs b/zxing.core/xx/datamatrix/encoder/DatamatrixEncodingOptions.cs deleted file mode 100644 index d78938e..0000000 --- a/zxing.core/xx/datamatrix/encoder/DatamatrixEncodingOptions.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 ZXing.Common; -using ZXing.Datamatrix.Encoder; - -namespace ZXing.Datamatrix -{ - /// - /// The class holds the available options for the DatamatrixWriter - /// - public class DatamatrixEncodingOptions : EncodingOptions - { - /// - /// Specifies the matrix shape for Data Matrix - /// - public SymbolShapeHint? SymbolShape - { - get - { - if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_SHAPE)) - { - return (SymbolShapeHint)Hints[EncodeHintType.DATA_MATRIX_SHAPE]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_SHAPE)) - Hints.Remove(EncodeHintType.DATA_MATRIX_SHAPE); - } - else - { - Hints[EncodeHintType.DATA_MATRIX_SHAPE] = value; - } - } - } - - /// - /// Specifies a minimum barcode size - /// - public Dimension MinSize - { - get - { - if (Hints.ContainsKey(EncodeHintType.MIN_SIZE)) - { - return (Dimension)Hints[EncodeHintType.MIN_SIZE]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.MIN_SIZE)) - Hints.Remove(EncodeHintType.MIN_SIZE); - } - else - { - Hints[EncodeHintType.MIN_SIZE] = value; - } - } - } - - /// - /// Specifies a maximum barcode size - /// - public Dimension MaxSize - { - get - { - if (Hints.ContainsKey(EncodeHintType.MAX_SIZE)) - { - return (Dimension)Hints[EncodeHintType.MAX_SIZE]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.MAX_SIZE)) - Hints.Remove(EncodeHintType.MAX_SIZE); - } - else - { - Hints[EncodeHintType.MAX_SIZE] = value; - } - } - } - - /// - /// Specifies the default encodation - /// Make sure that the content fits into the encodation value, otherwise there will be an exception thrown. - /// standard value: Encodation.ASCII - /// - public int? DefaultEncodation - { - get - { - if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION)) - { - return (int)Hints[EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION)) - Hints.Remove(EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION); - } - else - { - Hints[EncodeHintType.DATA_MATRIX_DEFAULT_ENCODATION] = value; - } - } - } - } -} diff --git a/zxing.core/xx/datamatrix/encoder/DefaultPlacement.cs b/zxing.core/xx/datamatrix/encoder/DefaultPlacement.cs deleted file mode 100644 index f3bd030..0000000 --- a/zxing.core/xx/datamatrix/encoder/DefaultPlacement.cs +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki. - * - * 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.Datamatrix.Encoder -{ - /// - /// Symbol Character Placement Program. Adapted from Annex M.1 in ISO/IEC 16022:2000(E). - /// - public class DefaultPlacement - { - private readonly String codewords; - private readonly int numrows; - private readonly int numcols; - private readonly byte[] bits; - - /// - /// Main constructor - /// - /// the codewords to place - /// the number of columns - /// the number of rows - public DefaultPlacement(String codewords, int numcols, int numrows) - { - this.codewords = codewords; - this.numcols = numcols; - this.numrows = numrows; - this.bits = new byte[numcols * numrows]; - SupportClass.Fill(this.bits, (byte)2); //Initialize with "not set" value - } - - public int Numrows - { - get { return numrows; } - } - - public int Numcols - { - get { return numcols; } - } - - public byte[] Bits - { - get { return bits; } - } - - public bool getBit(int col, int row) - { - return bits[row * numcols + col] == 1; - } - - public void setBit(int col, int row, bool bit) - { - bits[row * numcols + col] = bit ? (byte)1 : (byte)0; - } - - public bool hasBit(int col, int row) - { - return bits[row * numcols + col] < 2; - } - - public void place() - { - int pos = 0; - int row = 4; - int col = 0; - - do - { - /* repeatedly first check for one of the special corner cases, then... */ - if ((row == numrows) && (col == 0)) - { - corner1(pos++); - } - if ((row == numrows - 2) && (col == 0) && ((numcols % 4) != 0)) - { - corner2(pos++); - } - if ((row == numrows - 2) && (col == 0) && (numcols % 8 == 4)) - { - corner3(pos++); - } - if ((row == numrows + 4) && (col == 2) && ((numcols % 8) == 0)) - { - corner4(pos++); - } - /* sweep upward diagonally, inserting successive characters... */ - do - { - if ((row < numrows) && (col >= 0) && !hasBit(col, row)) - { - utah(row, col, pos++); - } - row -= 2; - col += 2; - } while (row >= 0 && (col < numcols)); - row++; - col += 3; - - /* and then sweep downward diagonally, inserting successive characters, ... */ - do - { - if ((row >= 0) && (col < numcols) && !hasBit(col, row)) - { - utah(row, col, pos++); - } - row += 2; - col -= 2; - } while ((row < numrows) && (col >= 0)); - row += 3; - col++; - - /* ...until the entire array is scanned */ - } while ((row < numrows) || (col < numcols)); - - /* Lastly, if the lower righthand corner is untouched, fill in fixed pattern */ - if (!hasBit(numcols - 1, numrows - 1)) - { - setBit(numcols - 1, numrows - 1, true); - setBit(numcols - 2, numrows - 2, true); - } - } - - private void module(int row, int col, int pos, int bit) - { - if (row < 0) - { - row += numrows; - col += 4 - ((numrows + 4) % 8); - } - if (col < 0) - { - col += numcols; - row += 4 - ((numcols + 4) % 8); - } - // Note the conversion: - int v = codewords[pos]; - v &= 1 << (8 - bit); - setBit(col, row, v != 0); - } - - /// - /// Places the 8 bits of a utah-shaped symbol character in ECC200. - /// - /// The row. - /// The col. - /// character position - private void utah(int row, int col, int pos) - { - module(row - 2, col - 2, pos, 1); - module(row - 2, col - 1, pos, 2); - module(row - 1, col - 2, pos, 3); - module(row - 1, col - 1, pos, 4); - module(row - 1, col, pos, 5); - module(row, col - 2, pos, 6); - module(row, col - 1, pos, 7); - module(row, col, pos, 8); - } - - private void corner1(int pos) - { - module(numrows - 1, 0, pos, 1); - module(numrows - 1, 1, pos, 2); - module(numrows - 1, 2, pos, 3); - module(0, numcols - 2, pos, 4); - module(0, numcols - 1, pos, 5); - module(1, numcols - 1, pos, 6); - module(2, numcols - 1, pos, 7); - module(3, numcols - 1, pos, 8); - } - - private void corner2(int pos) - { - module(numrows - 3, 0, pos, 1); - module(numrows - 2, 0, pos, 2); - module(numrows - 1, 0, pos, 3); - module(0, numcols - 4, pos, 4); - module(0, numcols - 3, pos, 5); - module(0, numcols - 2, pos, 6); - module(0, numcols - 1, pos, 7); - module(1, numcols - 1, pos, 8); - } - - private void corner3(int pos) - { - module(numrows - 3, 0, pos, 1); - module(numrows - 2, 0, pos, 2); - module(numrows - 1, 0, pos, 3); - module(0, numcols - 2, pos, 4); - module(0, numcols - 1, pos, 5); - module(1, numcols - 1, pos, 6); - module(2, numcols - 1, pos, 7); - module(3, numcols - 1, pos, 8); - } - - private void corner4(int pos) - { - module(numrows - 1, 0, pos, 1); - module(numrows - 1, numcols - 1, pos, 2); - module(0, numcols - 3, pos, 3); - module(0, numcols - 2, pos, 4); - module(0, numcols - 1, pos, 5); - module(1, numcols - 3, pos, 6); - module(1, numcols - 2, pos, 7); - module(1, numcols - 1, pos, 8); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/EdifactEncoder.cs b/zxing.core/xx/datamatrix/encoder/EdifactEncoder.cs deleted file mode 100644 index cd17d64..0000000 --- a/zxing.core/xx/datamatrix/encoder/EdifactEncoder.cs +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * 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.Text; - -namespace ZXing.Datamatrix.Encoder -{ - internal sealed class EdifactEncoder : Encoder - { - public int EncodingMode - { - get { return Encodation.EDIFACT; } - } - - public void encode(EncoderContext context) - { - //step F - var buffer = new StringBuilder(); - while (context.HasMoreCharacters) - { - char c = context.CurrentChar; - encodeChar(c, buffer); - context.Pos++; - - int count = buffer.Length; - if (count >= 4) - { - context.writeCodewords(encodeToCodewords(buffer, 0)); - buffer.Remove(0, 4); - - int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, EncodingMode); - if (newMode != EncodingMode) - { - context.signalEncoderChange(Encodation.ASCII); - break; - } - } - } - buffer.Append((char)31); //Unlatch - handleEOD(context, buffer); - } - - /// - /// Handle "end of data" situations - /// - /// the encoder context - /// the buffer with the remaining encoded characters - private static void handleEOD(EncoderContext context, StringBuilder buffer) - { - try - { - int count = buffer.Length; - if (count == 0) - { - return; //Already finished - } - if (count == 1) - { - //Only an unlatch at the end - context.updateSymbolInfo(); - int available = context.SymbolInfo.dataCapacity - context.CodewordCount; - int remaining = context.RemainingCharacters; - if (remaining == 0 && available <= 2) - { - return; //No unlatch - } - } - - if (count > 4) - { - throw new InvalidOperationException("Count must not exceed 4"); - } - int restChars = count - 1; - String encoded = encodeToCodewords(buffer, 0); - bool endOfSymbolReached = !context.HasMoreCharacters; - bool restInAscii = endOfSymbolReached && restChars <= 2; - - if (restChars <= 2) - { - context.updateSymbolInfo(context.CodewordCount + restChars); - int available = context.SymbolInfo.dataCapacity - context.CodewordCount; - if (available >= 3) - { - restInAscii = false; - context.updateSymbolInfo(context.CodewordCount + encoded.Length); - //available = context.symbolInfo.dataCapacity - context.getCodewordCount(); - } - } - - if (restInAscii) - { - context.resetSymbolInfo(); - context.Pos -= restChars; - } - else - { - context.writeCodewords(encoded); - } - } - finally - { - context.signalEncoderChange(Encodation.ASCII); - } - } - - private static void encodeChar(char c, StringBuilder sb) - { - if (c >= ' ' && c <= '?') - { - sb.Append(c); - } - else if (c >= '@' && c <= '^') - { - sb.Append((char)(c - 64)); - } - else - { - HighLevelEncoder.illegalCharacter(c); - } - } - - private static String encodeToCodewords(StringBuilder sb, int startPos) - { - int len = sb.Length - startPos; - if (len == 0) - { - throw new InvalidOperationException("StringBuilder must not be empty"); - } - char c1 = sb[startPos]; - char c2 = len >= 2 ? sb[startPos + 1] : (char)0; - char c3 = len >= 3 ? sb[startPos + 2] : (char)0; - char c4 = len >= 4 ? sb[startPos + 3] : (char)0; - - int v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4; - char cw1 = (char)((v >> 16) & 255); - char cw2 = (char)((v >> 8) & 255); - char cw3 = (char)(v & 255); - var res = new StringBuilder(3); - res.Append(cw1); - if (len >= 2) - { - res.Append(cw2); - } - if (len >= 3) - { - res.Append(cw3); - } - return res.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/Encodation.cs b/zxing.core/xx/datamatrix/encoder/Encodation.cs deleted file mode 100644 index ba83dc6..0000000 --- a/zxing.core/xx/datamatrix/encoder/Encodation.cs +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2013 - * - * 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.Datamatrix.Encoder -{ - /// - /// Enumeration for encodation types - /// - public sealed class Encodation - { - public const int ASCII = 0; - public const int C40 = 1; - public const int TEXT = 2; - public const int X12 = 3; - public const int EDIFACT = 4; - public const int BASE256 = 5; - } -} diff --git a/zxing.core/xx/datamatrix/encoder/Encoder.cs b/zxing.core/xx/datamatrix/encoder/Encoder.cs deleted file mode 100644 index 292976c..0000000 --- a/zxing.core/xx/datamatrix/encoder/Encoder.cs +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * 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.Datamatrix.Encoder -{ - internal interface Encoder - { - int EncodingMode { get; } - - void encode(EncoderContext context); - } -} diff --git a/zxing.core/xx/datamatrix/encoder/EncoderContext.cs b/zxing.core/xx/datamatrix/encoder/EncoderContext.cs deleted file mode 100644 index 627afe5..0000000 --- a/zxing.core/xx/datamatrix/encoder/EncoderContext.cs +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * 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.Text; - -namespace ZXing.Datamatrix.Encoder -{ - internal sealed class EncoderContext - { - private readonly String msg; - private SymbolShapeHint shape; - private Dimension minSize; - private Dimension maxSize; - private readonly StringBuilder codewords; - private int pos; - private int newEncoding; - private SymbolInfo symbolInfo; - private int skipAtEnd; - private static readonly Encoding encoding; - - static EncoderContext() - { -#if !(WindowsCE || SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE) - encoding = Encoding.GetEncoding("ISO-8859-1"); -#elif WindowsCE - try - { - encoding = Encoding.GetEncoding("ISO-8859-1"); - } - catch (PlatformNotSupportedException) - { - encoding = Encoding.GetEncoding(1252); - } -#else - // not fully correct but what else - encoding = Encoding.GetEncoding("UTF-8"); -#endif - } - - public EncoderContext(String msg) - { - //From this point on Strings are not Unicode anymore! - var msgBinary = encoding.GetBytes(msg); - var sb = new StringBuilder(msgBinary.Length); - var c = msgBinary.Length; - for (int i = 0; i < c; i++) - { - // TODO: does it works in .Net the same way? - var ch = (char)(msgBinary[i] & 0xff); - if (ch == '?' && msg[i] != '?') - { - throw new ArgumentException("Message contains characters outside " + encoding.WebName + " encoding."); - } - sb.Append(ch); - } - this.msg = sb.ToString(); //Not Unicode here! - shape = SymbolShapeHint.FORCE_NONE; - this.codewords = new StringBuilder(msg.Length); - newEncoding = -1; - } - - public void setSymbolShape(SymbolShapeHint shape) - { - this.shape = shape; - } - - public void setSizeConstraints(Dimension minSize, Dimension maxSize) - { - this.minSize = minSize; - this.maxSize = maxSize; - } - - public void setSkipAtEnd(int count) - { - this.skipAtEnd = count; - } - - public char CurrentChar - { - get { return msg[pos]; } - } - - public char Current - { - get { return msg[pos]; } - } - - public void writeCodewords(String codewords) - { - this.codewords.Append(codewords); - } - - public void writeCodeword(char codeword) - { - this.codewords.Append(codeword); - } - - public int CodewordCount - { - get { return this.codewords.Length; } - } - - public void signalEncoderChange(int encoding) - { - this.newEncoding = encoding; - } - - public void resetEncoderSignal() - { - this.newEncoding = -1; - } - - public bool HasMoreCharacters - { - get { return pos < TotalMessageCharCount; } - } - - private int TotalMessageCharCount - { - get { return msg.Length - skipAtEnd; } - } - - public int RemainingCharacters - { - get { return TotalMessageCharCount - pos; } - } - - public void updateSymbolInfo() - { - updateSymbolInfo(CodewordCount); - } - - public void updateSymbolInfo(int len) - { - if (this.symbolInfo == null || len > this.symbolInfo.dataCapacity) - { - this.symbolInfo = SymbolInfo.lookup(len, shape, minSize, maxSize, true); - } - } - - public void resetSymbolInfo() - { - this.symbolInfo = null; - } - - public int Pos - { - get { return pos; } - set { pos = value; } - } - - public StringBuilder Codewords - { - get { return codewords; } - } - - public SymbolInfo SymbolInfo - { - get { return symbolInfo; } - } - - public int NewEncoding - { - get { return newEncoding; } - } - - public String Message - { - get { return msg; } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/ErrorCorrection.cs b/zxing.core/xx/datamatrix/encoder/ErrorCorrection.cs deleted file mode 100644 index fabccae..0000000 --- a/zxing.core/xx/datamatrix/encoder/ErrorCorrection.cs +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki. - * - * 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.Text; - -namespace ZXing.Datamatrix.Encoder -{ - /// - /// Error Correction Code for ECC200. - /// - public static class ErrorCorrection - { - /// - /// Lookup table which factors to use for which number of error correction codewords. - /// See FACTORS. - /// - private static readonly int[] FACTOR_SETS - = { 5, 7, 10, 11, 12, 14, 18, 20, 24, 28, 36, 42, 48, 56, 62, 68 }; - - /// - /// Precomputed polynomial factors for ECC 200. - /// - private static readonly int[][] FACTORS = { - new[] {228, 48, 15, 111, 62}, - new[] {23, 68, 144, 134, 240, 92, 254}, - new[] {28, 24, 185, 166, 223, 248, 116, 255, 110, 61}, - new[] {175, 138, 205, 12, 194, 168, 39, 245, 60, 97, 120}, - new[] {41, 153, 158, 91, 61, 42, 142, 213, 97, 178, 100, 242}, - new[] {156, 97, 192, 252, 95, 9, 157, 119, 138, 45, 18, 186, 83, 185} - , - new[] - { - 83, 195, 100, 39, 188, 75, 66, 61, 241, 213, 109, 129, 94, 254, - 225, - 48, 90, 188 - }, - new[] - { - 15, 195, 244, 9, 233, 71, 168, 2, 188, 160, 153, 145, 253, 79, - 108, - 82, 27, 174, 186, 172 - }, - new[] - { - 52, 190, 88, 205, 109, 39, 176, 21, 155, 197, 251, 223, 155, 21 - , 5 - , 172, - 254, 124, 12, 181, 184, 96, 50, 193 - }, - new[] - { - 211, 231, 43, 97, 71, 96, 103, 174, 37, 151, 170, 53, 75, 34, - 249, - 121, - 17, 138, 110, 213, 141, 136, 120, 151, 233, 168, 93, 255 - }, - new[] - { - 245, 127, 242, 218, 130, 250, 162, 181, 102, 120, 84, 179, 220, - 251, 80, 182, - 229, 18, 2, 4, 68, 33, 101, 137, 95, 119, 115, 44, 175, 184, 59 - , - 25, - 225, 98, 81, 112 - }, - new[] - { - 77, 193, 137, 31, 19, 38, 22, 153, 247, 105, 122, 2, 245, 133, - 242 - , 8, - 175, 95, 100, 9, 167, 105, 214, 111, 57, 121, 21, 1, 253, 57, - 54, - 101, - 248, 202, 69, 50, 150, 177, 226, 5, 9, 5 - }, - new[] - { - 245, 132, 172, 223, 96, 32, 117, 22, 238, 133, 238, 231, 205, - 188, - 237, 87, - 191, 106, 16, 147, 118, 23, 37, 90, 170, 205, 131, 88, 120, 100 - , - 66, 138, - 186, 240, 82, 44, 176, 87, 187, 147, 160, 175, 69, 213, 92, 253 - , - 225, 19 - }, - new[] - { - 175, 9, 223, 238, 12, 17, 220, 208, 100, 29, 175, 170, 230, 192 - , - 215, 235, - 150, 159, 36, 223, 38, 200, 132, 54, 228, 146, 218, 234, 117, - 203, - 29, 232, - 144, 238, 22, 150, 201, 117, 62, 207, 164, 13, 137, 245, 127, - 67, - 247, 28, - 155, 43, 203, 107, 233, 53, 143, 46 - }, - new[] - { - 242, 93, 169, 50, 144, 210, 39, 118, 202, 188, 201, 189, 143, - 108, - 196, 37, - 185, 112, 134, 230, 245, 63, 197, 190, 250, 106, 185, 221, 175, - 64 - , 114, 71, - 161, 44, 147, 6, 27, 218, 51, 63, 87, 10, 40, 130, 188, 17, 163 - , - 31, - 176, 170, 4, 107, 232, 7, 94, 166, 224, 124, 86, 47, 11, 204 - }, - new[] - { - 220, 228, 173, 89, 251, 149, 159, 56, 89, 33, 147, 244, 154, 36 - , - 73, 127, - 213, 136, 248, 180, 234, 197, 158, 177, 68, 122, 93, 213, 15, - 160, - 227, 236, - 66, 139, 153, 185, 202, 167, 179, 25, 220, 232, 96, 210, 231, - 136, - 223, 239, - 181, 241, 59, 52, 172, 25, 49, 232, 211, 189, 64, 54, 108, 153, - 132, 63, - 96, 103, 82, 186 - } - }; - - private const int MODULO_VALUE = 0x12D; - - private static readonly int[] LOG; - private static readonly int[] ALOG; - - static ErrorCorrection() - { - //Create log and antilog table - LOG = new int[256]; - ALOG = new int[255]; - - int p = 1; - for (int i = 0; i < 255; i++) - { - ALOG[i] = p; - LOG[p] = i; - p <<= 1; - if (p >= 256) - { - p ^= MODULO_VALUE; - } - } - } - - /// - /// Creates the ECC200 error correction for an encoded message. - /// - /// The codewords. - /// information about the symbol to be encoded - /// the codewords with interleaved error correction. - public static String encodeECC200(String codewords, SymbolInfo symbolInfo) - { - if (codewords.Length != symbolInfo.dataCapacity) - { - throw new ArgumentException( - "The number of codewords does not match the selected symbol"); - } - var sb = new StringBuilder(symbolInfo.dataCapacity + symbolInfo.errorCodewords); - sb.Append(codewords); - int blockCount = symbolInfo.getInterleavedBlockCount(); - if (blockCount == 1) - { - String ecc = createECCBlock(codewords, symbolInfo.errorCodewords); - sb.Append(ecc); - } - else - { - sb.Length = sb.Capacity; - int[] dataSizes = new int[blockCount]; - int[] errorSizes = new int[blockCount]; - int[] startPos = new int[blockCount]; - for (int i = 0; i < blockCount; i++) - { - dataSizes[i] = symbolInfo.getDataLengthForInterleavedBlock(i + 1); - errorSizes[i] = symbolInfo.getErrorLengthForInterleavedBlock(i + 1); - startPos[i] = 0; - if (i > 0) - { - startPos[i] = startPos[i - 1] + dataSizes[i]; - } - } - for (int block = 0; block < blockCount; block++) - { - var temp = new StringBuilder(dataSizes[block]); - for (int d = block; d < symbolInfo.dataCapacity; d += blockCount) - { - temp.Append(codewords[d]); - } - String ecc = createECCBlock(temp.ToString(), errorSizes[block]); - int pos = 0; - for (int e = block; e < errorSizes[block] * blockCount; e += blockCount) - { - sb[symbolInfo.dataCapacity + e] = ecc[pos++]; - } - } - } - return sb.ToString(); - - } - - private static String createECCBlock(String codewords, int numECWords) - { - return createECCBlock(codewords, 0, codewords.Length, numECWords); - } - - private static String createECCBlock(String codewords, int start, int len, int numECWords) - { - int table = -1; - for (int i = 0; i < FACTOR_SETS.Length; i++) - { - if (FACTOR_SETS[i] == numECWords) - { - table = i; - break; - } - } - if (table < 0) - { - throw new ArgumentException( - "Illegal number of error correction codewords specified: " + numECWords); - } - int[] poly = FACTORS[table]; - char[] ecc = new char[numECWords]; - for (int i = 0; i < numECWords; i++) - { - ecc[i] = (char)0; - } - for (int i = start; i < start + len; i++) - { - int m = ecc[numECWords - 1] ^ codewords[i]; - for (int k = numECWords - 1; k > 0; k--) - { - if (m != 0 && poly[k] != 0) - { - ecc[k] = (char)(ecc[k - 1] ^ ALOG[(LOG[m] + LOG[poly[k]]) % 255]); - } - else - { - ecc[k] = ecc[k - 1]; - } - } - if (m != 0 && poly[0] != 0) - { - ecc[0] = (char)ALOG[(LOG[m] + LOG[poly[0]]) % 255]; - } - else - { - ecc[0] = (char)0; - } - } - char[] eccReversed = new char[numECWords]; - for (int i = 0; i < numECWords; i++) - { - eccReversed[i] = ecc[numECWords - i - 1]; - } - return new String(eccReversed); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/HighLevelEncoder.cs b/zxing.core/xx/datamatrix/encoder/HighLevelEncoder.cs deleted file mode 100644 index 96bd383..0000000 --- a/zxing.core/xx/datamatrix/encoder/HighLevelEncoder.cs +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * 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.Text; - -namespace ZXing.Datamatrix.Encoder -{ - /// - /// DataMatrix ECC 200 data encoder following the algorithm described in ISO/IEC 16022:200(E) in - /// annex S. - /// - internal static class HighLevelEncoder - { - /// - /// Padding character - /// - public const char PAD = (char)129; - /// - /// mode latch to C40 encodation mode - /// - public const char LATCH_TO_C40 = (char)230; - /// - /// mode latch to Base 256 encodation mode - /// - public const char LATCH_TO_BASE256 = (char)231; - /// - /// FNC1 Codeword - /// - public const char FNC1 = (char)232; - /// - /// Structured Append Codeword - /// - public const char STRUCTURED_APPEND = (char)233; - /// - /// Reader Programming - /// - public const char READER_PROGRAMMING = (char)234; - /// - /// Upper Shift - /// - public const char UPPER_SHIFT = (char)235; - /// - /// 05 Macro - /// - public const char MACRO_05 = (char)236; - /// - /// 06 Macro - /// - public const char MACRO_06 = (char)237; - /// - /// mode latch to ANSI X.12 encodation mode - /// - public const char LATCH_TO_ANSIX12 = (char)238; - /// - /// mode latch to Text encodation mode - /// - public const char LATCH_TO_TEXT = (char)239; - /// - /// mode latch to EDIFACT encodation mode - /// - public const char LATCH_TO_EDIFACT = (char)240; - /// - /// ECI character (Extended Channel Interpretation) - /// - public const char ECI = (char)241; - - /// - /// Unlatch from C40 encodation - /// - public const char C40_UNLATCH = (char)254; - /// - /// Unlatch from X12 encodation - /// - public const char X12_UNLATCH = (char)254; - - /// - /// 05 Macro header - /// - public const String MACRO_05_HEADER = "[)>\u001E05\u001D"; - /// - /// 06 Macro header - /// - public const String MACRO_06_HEADER = "[)>\u001E06\u001D"; - /// - /// Macro trailer - /// - public const String MACRO_TRAILER = "\u001E\u0004"; - - /* - /// - /// Converts the message to a byte array using the default encoding (cp437) as defined by the - /// specification - /// - /// the message - /// the byte array of the message - public static byte[] getBytesForMessage(String msg) - { - return Encoding.GetEncoding("CP437").GetBytes(msg); //See 4.4.3 and annex B of ISO/IEC 15438:2001(E) - } - */ - - private static char randomize253State(char ch, int codewordPosition) - { - int pseudoRandom = ((149 * codewordPosition) % 253) + 1; - int tempVariable = ch + pseudoRandom; - return tempVariable <= 254 ? (char)tempVariable : (char)(tempVariable - 254); - } - - /// - /// Performs message encoding of a DataMatrix message using the algorithm described in annex P - /// of ISO/IEC 16022:2000(E). - /// - /// the message - /// the encoded message (the char values range from 0 to 255) - public static String encodeHighLevel(String msg) - { - return encodeHighLevel(msg, SymbolShapeHint.FORCE_NONE, null, null, Encodation.ASCII); - } - - /// - /// Performs message encoding of a DataMatrix message using the algorithm described in annex P - /// of ISO/IEC 16022:2000(E). - /// - /// the message - /// requested shape. May be {@code SymbolShapeHint.FORCE_NONE},{@code SymbolShapeHint.FORCE_SQUARE} or {@code SymbolShapeHint.FORCE_RECTANGLE}. - /// the minimum symbol size constraint or null for no constraint - /// the maximum symbol size constraint or null for no constraint - /// the encoded message (the char values range from 0 to 255) - public static String encodeHighLevel(String msg, - SymbolShapeHint shape, - Dimension minSize, - Dimension maxSize, - int defaultEncodation) - { - //the codewords 0..255 are encoded as Unicode characters - Encoder[] encoders = - { - new ASCIIEncoder(), new C40Encoder(), new TextEncoder(), - new X12Encoder(), new EdifactEncoder(), new Base256Encoder() - }; - - var context = new EncoderContext(msg); - context.setSymbolShape(shape); - context.setSizeConstraints(minSize, maxSize); - - if (msg.StartsWith(MACRO_05_HEADER) && msg.EndsWith(MACRO_TRAILER)) - { - context.writeCodeword(MACRO_05); - context.setSkipAtEnd(2); - context.Pos += MACRO_05_HEADER.Length; - } - else if (msg.StartsWith(MACRO_06_HEADER) && msg.EndsWith(MACRO_TRAILER)) - { - context.writeCodeword(MACRO_06); - context.setSkipAtEnd(2); - context.Pos += MACRO_06_HEADER.Length; - } - - int encodingMode = defaultEncodation; //Default mode - switch (encodingMode) - { - case Encodation.BASE256: - context.writeCodeword(HighLevelEncoder.LATCH_TO_BASE256); - break; - case Encodation.C40: - context.writeCodeword(HighLevelEncoder.LATCH_TO_C40); - break; - case Encodation.X12: - context.writeCodeword(HighLevelEncoder.LATCH_TO_ANSIX12); - break; - case Encodation.TEXT: - context.writeCodeword(HighLevelEncoder.LATCH_TO_TEXT); - break; - case Encodation.EDIFACT: - context.writeCodeword(HighLevelEncoder.LATCH_TO_EDIFACT); - break; - case Encodation.ASCII: - break; - default: - throw new InvalidOperationException("Illegal mode: " + encodingMode); - } - while (context.HasMoreCharacters) - { - encoders[encodingMode].encode(context); - if (context.NewEncoding >= 0) - { - encodingMode = context.NewEncoding; - context.resetEncoderSignal(); - } - } - int len = context.Codewords.Length; - context.updateSymbolInfo(); - int capacity = context.SymbolInfo.dataCapacity; - if (len < capacity) - { - if (encodingMode != Encodation.ASCII && encodingMode != Encodation.BASE256) - { - context.writeCodeword('\u00fe'); //Unlatch (254) - } - } - //Padding - StringBuilder codewords = context.Codewords; - if (codewords.Length < capacity) - { - codewords.Append(PAD); - } - while (codewords.Length < capacity) - { - codewords.Append(randomize253State(PAD, codewords.Length + 1)); - } - - return context.Codewords.ToString(); - } - - internal static int lookAheadTest(String msg, int startpos, int currentMode) - { - if (startpos >= msg.Length) - { - return currentMode; - } - float[] charCounts; - //step J - if (currentMode == Encodation.ASCII) - { - charCounts = new [] { 0, 1, 1, 1, 1, 1.25f }; - } - else - { - charCounts = new [] { 1, 2, 2, 2, 2, 2.25f }; - charCounts[currentMode] = 0; - } - - int charsProcessed = 0; - while (true) - { - //step K - if ((startpos + charsProcessed) == msg.Length) - { - var min = Int32.MaxValue; - var mins = new byte[6]; - var intCharCounts = new int[6]; - min = findMinimums(charCounts, intCharCounts, min, mins); - var minCount = getMinimumCount(mins); - - if (intCharCounts[Encodation.ASCII] == min) - { - return Encodation.ASCII; - } - if (minCount == 1 && mins[Encodation.BASE256] > 0) - { - return Encodation.BASE256; - } - if (minCount == 1 && mins[Encodation.EDIFACT] > 0) - { - return Encodation.EDIFACT; - } - if (minCount == 1 && mins[Encodation.TEXT] > 0) - { - return Encodation.TEXT; - } - if (minCount == 1 && mins[Encodation.X12] > 0) - { - return Encodation.X12; - } - return Encodation.C40; - } - - char c = msg[startpos + charsProcessed]; - charsProcessed++; - - //step L - if (isDigit(c)) - { - charCounts[Encodation.ASCII] += 0.5f; - } - else if (isExtendedASCII(c)) - { - charCounts[Encodation.ASCII] = (int)Math.Ceiling(charCounts[Encodation.ASCII]); - charCounts[Encodation.ASCII] += 2; - } - else - { - charCounts[Encodation.ASCII] = (int)Math.Ceiling(charCounts[Encodation.ASCII]); - charCounts[Encodation.ASCII]++; - } - - //step M - if (isNativeC40(c)) - { - charCounts[Encodation.C40] += 2.0f / 3.0f; - } - else if (isExtendedASCII(c)) - { - charCounts[Encodation.C40] += 8.0f / 3.0f; - } - else - { - charCounts[Encodation.C40] += 4.0f / 3.0f; - } - - //step N - if (isNativeText(c)) - { - charCounts[Encodation.TEXT] += 2.0f / 3.0f; - } - else if (isExtendedASCII(c)) - { - charCounts[Encodation.TEXT] += 8.0f / 3.0f; - } - else - { - charCounts[Encodation.TEXT] += 4.0f / 3.0f; - } - - //step O - if (isNativeX12(c)) - { - charCounts[Encodation.X12] += 2.0f / 3.0f; - } - else if (isExtendedASCII(c)) - { - charCounts[Encodation.X12] += 13.0f / 3.0f; - } - else - { - charCounts[Encodation.X12] += 10.0f / 3.0f; - } - - //step P - if (isNativeEDIFACT(c)) - { - charCounts[Encodation.EDIFACT] += 3.0f / 4.0f; - } - else if (isExtendedASCII(c)) - { - charCounts[Encodation.EDIFACT] += 17.0f / 4.0f; - } - else - { - charCounts[Encodation.EDIFACT] += 13.0f / 4.0f; - } - - // step Q - if (isSpecialB256(c)) - { - charCounts[Encodation.BASE256] += 4; - } - else - { - charCounts[Encodation.BASE256]++; - } - - //step R - if (charsProcessed >= 4) - { - var intCharCounts = new int[6]; - var mins = new byte[6]; - findMinimums(charCounts, intCharCounts, Int32.MaxValue, mins); - int minCount = getMinimumCount(mins); - - if (intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.BASE256] - && intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.C40] - && intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.TEXT] - && intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.X12] - && intCharCounts[Encodation.ASCII] < intCharCounts[Encodation.EDIFACT]) - { - return Encodation.ASCII; - } - if (intCharCounts[Encodation.BASE256] < intCharCounts[Encodation.ASCII] - || (mins[Encodation.C40] + mins[Encodation.TEXT] + mins[Encodation.X12] + mins[Encodation.EDIFACT]) == 0) - { - return Encodation.BASE256; - } - if (minCount == 1 && mins[Encodation.EDIFACT] > 0) - { - return Encodation.EDIFACT; - } - if (minCount == 1 && mins[Encodation.TEXT] > 0) - { - return Encodation.TEXT; - } - if (minCount == 1 && mins[Encodation.X12] > 0) - { - return Encodation.X12; - } - if (intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.ASCII] - && intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.BASE256] - && intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.EDIFACT] - && intCharCounts[Encodation.C40] + 1 < intCharCounts[Encodation.TEXT]) - { - if (intCharCounts[Encodation.C40] < intCharCounts[Encodation.X12]) - { - return Encodation.C40; - } - if (intCharCounts[Encodation.C40] == intCharCounts[Encodation.X12]) - { - int p = startpos + charsProcessed + 1; - while (p < msg.Length) - { - char tc = msg[p]; - if (isX12TermSep(tc)) - { - return Encodation.X12; - } - if (!isNativeX12(tc)) - { - break; - } - p++; - } - return Encodation.C40; - } - } - } - } - } - - private static int findMinimums(float[] charCounts, int[] intCharCounts, int min, byte[] mins) - { - SupportClass.Fill(mins, (byte)0); - for (int i = 0; i < 6; i++) - { - intCharCounts[i] = (int)Math.Ceiling(charCounts[i]); - int current = intCharCounts[i]; - if (min > current) - { - min = current; - SupportClass.Fill(mins, (byte)0); - } - if (min == current) - { - mins[i]++; - - } - } - return min; - } - - private static int getMinimumCount(byte[] mins) - { - int minCount = 0; - for (int i = 0; i < 6; i++) - { - minCount += mins[i]; - } - return minCount; - } - - internal static bool isDigit(char ch) - { - return ch >= '0' && ch <= '9'; - } - - internal static bool isExtendedASCII(char ch) - { - return ch >= 128 && ch <= 255; - } - - internal static bool isNativeC40(char ch) - { - return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'); - } - - internal static bool isNativeText(char ch) - { - return (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z'); - } - - internal static bool isNativeX12(char ch) - { - return isX12TermSep(ch) || (ch == ' ') || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'); - } - - internal static bool isX12TermSep(char ch) - { - return (ch == '\r') //CR - || (ch == '*') - || (ch == '>'); - } - - internal static bool isNativeEDIFACT(char ch) - { - return ch >= ' ' && ch <= '^'; - } - - internal static bool isSpecialB256(char ch) - { - return false; //TODO NOT IMPLEMENTED YET!!! - } - - /// - /// Determines the number of consecutive characters that are encodable using numeric compaction. - /// - /// the message - /// the start position within the message - /// the requested character count - public static int determineConsecutiveDigitCount(String msg, int startpos) - { - int count = 0; - int len = msg.Length; - int idx = startpos; - if (idx < len) - { - char ch = msg[idx]; - while (isDigit(ch) && idx < len) - { - count++; - idx++; - if (idx < len) - { - ch = msg[idx]; - } - } - } - return count; - } - - internal static void illegalCharacter(char c) - { - throw new ArgumentException(String.Format("Illegal character: {0} (0x{1:X})", c, (int)c)); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/SymbolInfo.cs b/zxing.core/xx/datamatrix/encoder/SymbolInfo.cs deleted file mode 100644 index f746013..0000000 --- a/zxing.core/xx/datamatrix/encoder/SymbolInfo.cs +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki - * - * 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.Text; - -namespace ZXing.Datamatrix.Encoder -{ - /// - /// Symbol info table for DataMatrix. - /// - public class SymbolInfo - { - internal static readonly SymbolInfo[] PROD_SYMBOLS = { - new SymbolInfo(false, 3, 5, 8, 8, 1), - new SymbolInfo(false, 5, 7, 10, 10, 1), - /*rect*/new SymbolInfo(true, 5, 7, 16, 6, 1), - new SymbolInfo(false, 8, 10, 12, 12, 1), - /*rect*/new SymbolInfo(true, 10, 11, 14, 6, 2), - new SymbolInfo(false, 12, 12, 14, 14, 1), - /*rect*/new SymbolInfo(true, 16, 14, 24, 10, 1), - - new SymbolInfo(false, 18, 14, 16, 16, 1), - new SymbolInfo(false, 22, 18, 18, 18, 1), - /*rect*/new SymbolInfo(true, 22, 18, 16, 10, 2), - new SymbolInfo(false, 30, 20, 20, 20, 1), - /*rect*/new SymbolInfo(true, 32, 24, 16, 14, 2), - new SymbolInfo(false, 36, 24, 22, 22, 1), - new SymbolInfo(false, 44, 28, 24, 24, 1), - /*rect*/new SymbolInfo(true, 49, 28, 22, 14, 2), - - new SymbolInfo(false, 62, 36, 14, 14, 4), - new SymbolInfo(false, 86, 42, 16, 16, 4), - new SymbolInfo(false, 114, 48, 18, 18, 4), - new SymbolInfo(false, 144, 56, 20, 20, 4), - new SymbolInfo(false, 174, 68, 22, 22, 4), - - new SymbolInfo(false, 204, 84, 24, 24, 4, 102, 42), - new SymbolInfo(false, 280, 112, 14, 14, 16, 140, 56), - new SymbolInfo(false, 368, 144, 16, 16, 16, 92, 36), - new SymbolInfo(false, 456, 192, 18, 18, 16, 114, 48), - new SymbolInfo(false, 576, 224, 20, 20, 16, 144, 56), - new SymbolInfo(false, 696, 272, 22, 22, 16, 174, 68), - new SymbolInfo(false, 816, 336, 24, 24, 16, 136, 56), - new SymbolInfo(false, 1050, 408, 18, 18, 36, 175, 68), - new SymbolInfo(false, 1304, 496, 20, 20, 36, 163, 62), - new DataMatrixSymbolInfo144(), - }; - - private static SymbolInfo[] symbols = PROD_SYMBOLS; - - /** - * Overrides the symbol info set used by this class. Used for testing purposes. - * - * @param override the symbol info set to use - */ - public static void overrideSymbolSet(SymbolInfo[] @override) - { - symbols = @override; - } - - private readonly bool rectangular; - internal readonly int dataCapacity; - internal readonly int errorCodewords; - public readonly int matrixWidth; - public readonly int matrixHeight; - private readonly int dataRegions; - private readonly int rsBlockData; - private readonly int rsBlockError; - - public SymbolInfo(bool rectangular, int dataCapacity, int errorCodewords, - int matrixWidth, int matrixHeight, int dataRegions) - : this(rectangular, dataCapacity, errorCodewords, matrixWidth, matrixHeight, dataRegions, - dataCapacity, errorCodewords) - { - } - - internal SymbolInfo(bool rectangular, int dataCapacity, int errorCodewords, - int matrixWidth, int matrixHeight, int dataRegions, - int rsBlockData, int rsBlockError) - { - this.rectangular = rectangular; - this.dataCapacity = dataCapacity; - this.errorCodewords = errorCodewords; - this.matrixWidth = matrixWidth; - this.matrixHeight = matrixHeight; - this.dataRegions = dataRegions; - this.rsBlockData = rsBlockData; - this.rsBlockError = rsBlockError; - } - - public static SymbolInfo lookup(int dataCodewords) - { - return lookup(dataCodewords, SymbolShapeHint.FORCE_NONE, true); - } - - public static SymbolInfo lookup(int dataCodewords, SymbolShapeHint shape) - { - return lookup(dataCodewords, shape, true); - } - - public static SymbolInfo lookup(int dataCodewords, bool allowRectangular, bool fail) - { - SymbolShapeHint shape = allowRectangular - ? SymbolShapeHint.FORCE_NONE : SymbolShapeHint.FORCE_SQUARE; - return lookup(dataCodewords, shape, fail); - } - - private static SymbolInfo lookup(int dataCodewords, SymbolShapeHint shape, bool fail) - { - return lookup(dataCodewords, shape, null, null, fail); - } - - public static SymbolInfo lookup(int dataCodewords, - SymbolShapeHint shape, - Dimension minSize, - Dimension maxSize, - bool fail) - { - foreach (SymbolInfo symbol in symbols) - { - if (shape == SymbolShapeHint.FORCE_SQUARE && symbol.rectangular) - { - continue; - } - if (shape == SymbolShapeHint.FORCE_RECTANGLE && !symbol.rectangular) - { - continue; - } - if (minSize != null - && (symbol.getSymbolWidth() < minSize.Width - || symbol.getSymbolHeight() < minSize.Height)) - { - continue; - } - if (maxSize != null - && (symbol.getSymbolWidth() > maxSize.Width - || symbol.getSymbolHeight() > maxSize.Height)) - { - continue; - } - if (dataCodewords <= symbol.dataCapacity) - { - return symbol; - } - } - if (fail) - { - throw new ArgumentException( - "Can't find a symbol arrangement that matches the message. Data codewords: " - + dataCodewords); - } - return null; - } - - int getHorizontalDataRegions() - { - switch (dataRegions) - { - case 1: - return 1; - case 2: - return 2; - case 4: - return 2; - case 16: - return 4; - case 36: - return 6; - default: - throw new InvalidOperationException("Cannot handle this number of data regions"); - } - } - - int getVerticalDataRegions() - { - switch (dataRegions) - { - case 1: - return 1; - case 2: - return 1; - case 4: - return 2; - case 16: - return 4; - case 36: - return 6; - default: - throw new InvalidOperationException("Cannot handle this number of data regions"); - } - } - - public int getSymbolDataWidth() - { - return getHorizontalDataRegions() * matrixWidth; - } - - public int getSymbolDataHeight() - { - return getVerticalDataRegions() * matrixHeight; - } - - public int getSymbolWidth() - { - return getSymbolDataWidth() + (getHorizontalDataRegions() * 2); - } - - public int getSymbolHeight() - { - return getSymbolDataHeight() + (getVerticalDataRegions() * 2); - } - - public int getCodewordCount() - { - return dataCapacity + errorCodewords; - } - - virtual public int getInterleavedBlockCount() - { - return dataCapacity / rsBlockData; - } - - virtual public int getDataLengthForInterleavedBlock(int index) - { - return rsBlockData; - } - - public int getErrorLengthForInterleavedBlock(int index) - { - return rsBlockError; - } - - public override String ToString() - { - var sb = new StringBuilder(); - sb.Append(rectangular ? "Rectangular Symbol:" : "Square Symbol:"); - sb.Append(" data region ").Append(matrixWidth).Append('x').Append(matrixHeight); - sb.Append(", symbol size ").Append(getSymbolWidth()).Append('x').Append(getSymbolHeight()); - sb.Append(", symbol data size ").Append(getSymbolDataWidth()).Append('x').Append(getSymbolDataHeight()); - sb.Append(", codewords ").Append(dataCapacity).Append('+').Append(errorCodewords); - return sb.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/SymbolShapeHint.cs b/zxing.core/xx/datamatrix/encoder/SymbolShapeHint.cs deleted file mode 100644 index 66fee11..0000000 --- a/zxing.core/xx/datamatrix/encoder/SymbolShapeHint.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2007 Jeremias Maerki. - * - * 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.Datamatrix.Encoder -{ - /// - /// Enumeration for DataMatrix symbol shape hint. It can be used to force square or rectangular - /// symbols. - /// - public enum SymbolShapeHint - { - FORCE_NONE, - FORCE_SQUARE, - FORCE_RECTANGLE, - } -} diff --git a/zxing.core/xx/datamatrix/encoder/TextEncoder.cs b/zxing.core/xx/datamatrix/encoder/TextEncoder.cs deleted file mode 100644 index 6f6d5ba..0000000 --- a/zxing.core/xx/datamatrix/encoder/TextEncoder.cs +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Text; - -namespace ZXing.Datamatrix.Encoder -{ - internal sealed class TextEncoder : C40Encoder - { - override public int EncodingMode - { - get { return Encodation.TEXT; } - } - - override protected int encodeChar(char c, StringBuilder sb) - { - if (c == ' ') - { - sb.Append('\u0003'); - return 1; - } - if (c >= '0' && c <= '9') - { - sb.Append((char)(c - 48 + 4)); - return 1; - } - if (c >= 'a' && c <= 'z') - { - sb.Append((char)(c - 97 + 14)); - return 1; - } - if (c >= '\u0000' && c <= '\u001f') - { - sb.Append('\u0000'); //Shift 1 Set - sb.Append(c); - return 2; - } - if (c >= '!' && c <= '/') - { - sb.Append('\u0001'); //Shift 2 Set - sb.Append((char)(c - 33)); - return 2; - } - if (c >= ':' && c <= '@') - { - sb.Append('\u0001'); //Shift 2 Set - sb.Append((char)(c - 58 + 15)); - return 2; - } - if (c >= '[' && c <= '_') - { - sb.Append('\u0001'); //Shift 2 Set - sb.Append((char)(c - 91 + 22)); - return 2; - } - if (c == '\u0060') - { - sb.Append('\u0002'); //Shift 3 Set - sb.Append((char)(c - 96)); - return 2; - } - if (c >= 'A' && c <= 'Z') - { - sb.Append('\u0002'); //Shift 3 Set - sb.Append((char)(c - 65 + 1)); - return 2; - } - if (c >= '{' && c <= '\u007f') - { - sb.Append('\u0002'); //Shift 3 Set - sb.Append((char)(c - 123 + 27)); - return 2; - } - if (c >= '\u0080') - { - sb.Append("\u0001\u001e"); //Shift 2, Upper Shift - int len = 2; - len += encodeChar((char)(c - 128), sb); - return len; - } - HighLevelEncoder.illegalCharacter(c); - return -1; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/datamatrix/encoder/X12Encoder.cs b/zxing.core/xx/datamatrix/encoder/X12Encoder.cs deleted file mode 100644 index 02d04a2..0000000 --- a/zxing.core/xx/datamatrix/encoder/X12Encoder.cs +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2006-2007 Jeremias Maerki. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Text; - -namespace ZXing.Datamatrix.Encoder -{ - internal sealed class X12Encoder : C40Encoder - { - public override int EncodingMode - { - get { return Encodation.X12; } - } - - public override void encode(EncoderContext context) - { - //step C - var buffer = new StringBuilder(); - int currentMode = EncodingMode; - while (context.HasMoreCharacters) - { - char c = context.CurrentChar; - context.Pos++; - - encodeChar(c, buffer); - - int count = buffer.Length; - if ((count%3) == 0) - { - writeNextTriplet(context, buffer); - - int newMode = HighLevelEncoder.lookAheadTest(context.Message, context.Pos, currentMode); - if (newMode != currentMode) - { - context.signalEncoderChange(newMode); - break; - } - } - } - handleEOD(context, buffer); - } - - protected override int encodeChar(char c, StringBuilder sb) - { - if (c == '\r') - { - sb.Append('\u0000'); - } - else if (c == '*') - { - sb.Append('\u0001'); - } - else if (c == '>') - { - sb.Append('\u0002'); - } - else if (c == ' ') - { - sb.Append('\u0003'); - } - else if (c >= '0' && c <= '9') - { - sb.Append((char) (c - 48 + 4)); - } - else if (c >= 'A' && c <= 'Z') - { - sb.Append((char) (c - 65 + 14)); - } - else - { - HighLevelEncoder.illegalCharacter(c); - } - return 1; - } - - protected override void handleEOD(EncoderContext context, StringBuilder buffer) - { - context.updateSymbolInfo(); - int available = context.SymbolInfo.dataCapacity - context.CodewordCount; - int count = buffer.Length; - context.Pos -= count; - if (context.RemainingCharacters > 1 || available > 1 || - context.RemainingCharacters != available) - context.writeCodeword(HighLevelEncoder.X12_UNLATCH); - if (context.NewEncoding < 0) - context.signalEncoderChange(Encodation.ASCII); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.doc.shfbproj b/zxing.core/xx/documentation/zxing.doc.shfbproj deleted file mode 100644 index 4bdf894..0000000 --- a/zxing.core/xx/documentation/zxing.doc.shfbproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {8faf2142-c26e-4d13-9701-f86f6e6d0443} - 1.9.3.0 - - zxing.doc - zxing.doc - zxing.doc - - ..\..\..\Build\Release\Documentation\net4.0\ - zxing.net - en-US - - - - - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - AllMessages - HtmlHelp1 - False - .NET 4.0.30319 - False - False - False - True - - - - - - - - - - - - - - - - - - - - ..\..\..\Build\Release\Documentation\net4.0\ - - - - zxing - {6431cf13-7a7b-4602-b96a-47cda6f0b008} - True - - - zxing.presentation - {ea513204-63f3-4c50-992d-08ff430b6f70} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.net2.0.doc.shfbproj b/zxing.core/xx/documentation/zxing.net2.0.doc.shfbproj deleted file mode 100644 index c988b0f..0000000 --- a/zxing.core/xx/documentation/zxing.net2.0.doc.shfbproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {12441bd6-6380-40f8-b6f6-c42a98443bba} - 1.9.3.0 - - zxing.net2.0.doc - zxing.net2.0.doc - zxing.net2.0.doc - - ..\..\..\Build\Release\Documentation\net2.0\ - zxing.net2.0 - en-US - - - - AllMessages - HtmlHelp1 - False - .NET 2.0.50727 - False - False - False - True - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - - - - - - - - - - - - - - - zxing.net2.0 - {41b69545-aab6-42a6-96a0-6f6817e654a3} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.net3.5.doc.shfbproj b/zxing.core/xx/documentation/zxing.net3.5.doc.shfbproj deleted file mode 100644 index f4ee722..0000000 --- a/zxing.core/xx/documentation/zxing.net3.5.doc.shfbproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {0ddd7a5d-c54a-4841-8555-7940db210df7} - 1.9.3.0 - - zxing.net3.5.doc - zxing.net3.5.doc - zxing.net3.5.doc - - ..\..\..\Build\Release\Documentation\net3.5\ - zxing.net3.5 - en-US - - - - AllMessages - HtmlHelp1 - False - .NET 3.5 - False - False - False - True - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - - - - - - - - - - - - - - - zxing.net3.5 - {41b69545-aab6-42a6-96a0-6f6817e654a3} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.portable.doc.shfbproj b/zxing.core/xx/documentation/zxing.portable.doc.shfbproj deleted file mode 100644 index 36eed4e..0000000 --- a/zxing.core/xx/documentation/zxing.portable.doc.shfbproj +++ /dev/null @@ -1,80 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {B95B1194-0D6A-4121-A629-695B1F8EF0A7} - 1.9.3.0 - - zxing.portable.doc - zxing.portable.doc - zxing.portable.doc - - ..\..\..\Build\Release\Documentation\portable\ - zxing.net.portable - en-US - - - - Standard - Blank - False - vs2010 - False - Portable 4.0 - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - AllMessages - HtmlHelp1 - False - Portable 4.0 - False - False - False - True - - - - - - - - - - - - - - - - - - - - ..\..\..\Build\Release\Documentation\portable\ - - - - zxing.portable - {24b441f2-cbe9-4405-9fd0-72ebcbea0ec3} - True - - - - - System.Core - System.Core.dll - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.sl4.doc.shfbproj b/zxing.core/xx/documentation/zxing.sl4.doc.shfbproj deleted file mode 100644 index 85a5eb2..0000000 --- a/zxing.core/xx/documentation/zxing.sl4.doc.shfbproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {f983b572-dcd7-4ab4-b9d5-d218a22ba5fe} - 1.9.3.0 - - zxing.sl4.doc - zxing.sl4.doc - zxing.sl4.doc - - ..\..\..\Build\Release\Documentation\sl4\ - zxing.sl4 - en-US - - - - AllMessages - HtmlHelp1 - False - Silverlight 4.0 - False - False - False - True - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - - - - - - - - - - - - - - - zxing.sl4 - {03b962bb-7a24-4589-89e5-c42a17ddc376} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.sl5.doc.shfbproj b/zxing.core/xx/documentation/zxing.sl5.doc.shfbproj deleted file mode 100644 index deeaa6c..0000000 --- a/zxing.core/xx/documentation/zxing.sl5.doc.shfbproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {cd937642-91a0-4371-9452-336f8cc63121} - 1.9.3.0 - - zxing.sl5.doc - zxing.sl5.doc - zxing.sl5.doc - - ..\..\..\Build\Release\Documentation\sl5\ - zxing.sl5 - en-US - - - - AllMessages - HtmlHelp1 - False - Silverlight 5.0 - False - False - False - True - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - - - - - - - - - - - - - - - zxing.sl5 - {a3d48b9c-42a0-4fc8-bb58-d368f239debf} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.unity.doc.shfbproj b/zxing.core/xx/documentation/zxing.unity.doc.shfbproj deleted file mode 100644 index ce966be..0000000 --- a/zxing.core/xx/documentation/zxing.unity.doc.shfbproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {9ab81466-791f-46b2-ae88-55d4759de821} - 1.9.3.0 - - zxing.unity.doc - zxing.unity.doc - zxing.unity.doc - - ..\..\..\Build\Release\Documentation\unity\ - zxing.unity - en-US - - - - AllMessages - HtmlHelp1 - False - .NET 3.5 - False - False - False - True - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - - - - - - - - - - - - - - - zxing.unity - {fd386cf5-e9cd-442c-a44c-b7d996e68ccc} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.wp7.0.doc.shfbproj b/zxing.core/xx/documentation/zxing.wp7.0.doc.shfbproj deleted file mode 100644 index 782e4e7..0000000 --- a/zxing.core/xx/documentation/zxing.wp7.0.doc.shfbproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {5fbc3f17-7792-46ce-b974-14753d605a18} - 1.9.3.0 - - zxing.wp7.0.doc - zxing.wp7.0.doc - zxing.wp7.0.doc - - ..\..\..\Build\Release\Documentation\wp7.0\ - zxing.wp7.0 - en-US - - - - AllMessages - HtmlHelp1 - False - Silverlight 4.0 - False - False - False - True - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - - - - - - - - - - - - - - - zxing.wp7.0 - {7144c757-8ca7-4433-8c6f-072c24c43c62} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/documentation/zxing.wp7.1.doc.shfbproj b/zxing.core/xx/documentation/zxing.wp7.1.doc.shfbproj deleted file mode 100644 index 3d5a4a9..0000000 --- a/zxing.core/xx/documentation/zxing.wp7.1.doc.shfbproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {13addaba-9d04-4503-a9ff-c39e96b6e6b4} - 1.9.3.0 - - zxing.wp7.1.doc - zxing.wp7.1.doc - zxing.wp7.1.doc - - ..\..\..\Build\Release\Documentation\wp7.1\ - zxing.wp7.1 - en-US - - - - AllMessages - HtmlHelp1 - False - Silverlight 4.0 - False - False - False - True - Standard - Blank - False - vs2010 - False - Guid - ZXing.Net - AboveNamespaces - Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected - - - - - - - - - - - - - - - - - - - - - zxing.wp7.1 - {ec6f52b8-af75-4fa2-85c1-82bf77861fff} - True - - - - - \ No newline at end of file diff --git a/zxing.core/xx/imb/IMBReader.cs b/zxing.core/xx/imb/IMBReader.cs deleted file mode 100644 index 07cf0a4..0000000 --- a/zxing.core/xx/imb/IMBReader.cs +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Copyright 2014 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.Numerics; -using System.Text; - -using ZXing.Common; -using ZXing.OneD; - -namespace ZXing.IMB -{ - /// - /// implements an Intelligent Mail barcode - /// Rishabh Hatgadkar - /// - public sealed class IMBReader : OneDReader - { - private const int NUM_BARS_IMB = 65; - - private static readonly int[] barPosA = new[] {2, 6, 13, 16, 21, 30, 34, 40, 45, 48, 52, 56, 62}; - private static readonly int[] barPosB = new[] {22, 18, 39, 41, 11, 57, 54, 50, 7, 32, 2, 62, 26}; - private static readonly int[] barPosC = new[] {40, 35, 57, 52, 49, 7, 24, 17, 3, 63, 29, 44, 12}; - private static readonly int[] barPosD = new[] {47, 5, 35, 39, 30, 42, 15, 60, 20, 10, 65, 54, 23}; - private static readonly int[] barPosE = new[] {20, 41, 46, 1, 8, 51, 29, 61, 34, 15, 25, 37, 58}; - private static readonly int[] barPosF = new[] {51, 25, 19, 64, 56, 4, 44, 31, 28, 36, 47, 11, 6}; - private static readonly int[] barPosG = new[] {33, 37, 21, 9, 17, 49, 59, 14, 64, 26, 42, 4, 53}; - private static readonly int[] barPosH = new[] {60, 14, 1, 27, 38, 61, 10, 24, 50, 55, 19, 32, 45}; - private static readonly int[] barPosI = new[] {27, 46, 65, 59, 31, 12, 16, 43, 55, 5, 9, 22, 36}; - private static readonly int[] barPosJ = new[] {63, 58, 53, 48, 43, 38, 33, 28, 23, 18, 13, 8, 3}; - private static readonly int[][] barPos = new[] {barPosA, barPosB, barPosC, barPosD, barPosE, barPosF, barPosG, barPosH, barPosI, barPosJ}; - - private static readonly char[] barTypeA = new[] {'A', 'D', 'A', 'D', 'A', 'A', 'D', 'D', 'D', 'A', 'A', 'A', 'D'}; - private static readonly char[] barTypeB = new[] {'A', 'D', 'A', 'D', 'A', 'D', 'A', 'A', 'A', 'A', 'D', 'A', 'D'}; - private static readonly char[] barTypeC = new[] {'A', 'D', 'A', 'D', 'A', 'D', 'D', 'A', 'A', 'D', 'A', 'D', 'A'}; - private static readonly char[] barTypeD = new[] {'A', 'A', 'A', 'D', 'D', 'A', 'D', 'A', 'A', 'D', 'D', 'D', 'A'}; - private static readonly char[] barTypeE = new[] {'D', 'A', 'D', 'A', 'D', 'A', 'D', 'D', 'A', 'A', 'A', 'D', 'A'}; - private static readonly char[] barTypeF = new[] {'D', 'D', 'A', 'A', 'D', 'D', 'A', 'A', 'D', 'D', 'D', 'D', 'A'}; - private static readonly char[] barTypeG = new[] {'D', 'A', 'D', 'D', 'D', 'D', 'A', 'A', 'D', 'A', 'D', 'A', 'D'}; - private static readonly char[] barTypeH = new[] {'D', 'D', 'D', 'D', 'A', 'A', 'A', 'A', 'D', 'A', 'D', 'D', 'A'}; - private static readonly char[] barTypeI = new[] {'A', 'A', 'A', 'D', 'D', 'D', 'A', 'D', 'D', 'D', 'A', 'D', 'A'}; - private static readonly char[] barTypeJ = new[] {'A', 'D', 'A', 'D', 'A', 'D', 'A', 'A', 'D', 'A', 'D', 'A', 'D'}; - private static readonly char[][] barType = new[] {barTypeA, barTypeB, barTypeC, barTypeD, barTypeE, barTypeF, barTypeG, barTypeH, barTypeI, barTypeJ}; - - private const int A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, I = 8, J = 9; - - private static readonly IDictionary table1Check; - private static readonly IDictionary table2Check; - - private BinaryBitmap currentBitmap; - - static IMBReader() - { - ushort[] table1 = {31, 7936, 47, 7808, 55, 7552, 59, 7040, 61, 6016, 62, 3968, 79, 7744, 87, 7488, 91, 6976, 93, 5952, 94, 3904, 103, 7360, 107, 6848, 109, 5824, 110, 3776, 115, 6592, 117, 5568, 118, 3520, 121, 5056, 122, 3008, 124, 1984, 143, 7712, 151, 7456, 155, 6944, 157, 5920, 158, 3872, 167, 7328, 171, 6816, 173, 5792, 174, 3744, 179, 6560, 181, 5536, 182, 3488, 185, 5024, 186, 2976, 188, 1952, 199, 7264, 203, 6752, 205, 5728, 206, 3680, 211, 6496, 213, 5472, 214, 3424, 217, 4960, 218, 2912, 220, 1888, 227, 6368, 229, 5344, 230, 3296, 233, 4832, 234, 2784, 236, 1760, 241, 4576, 242, 2528, 244, 1504, 248, 992, 271, 7696, 279, 7440, 283, 6928, 285, 5904, 286, 3856, 295, 7312, 299, 6800, 301, 5776, 302, 3728, 307, 6544, 309, 5520, 310, 3472, 313, 5008, 314, 2960, 316, 1936, 327, 7248, 331, 6736, 333, 5712, 334, 3664, 339, 6480, 341, 5456, 342, 3408, 345, 4944, 346, 2896, 348, 1872, 355, 6352, 357, 5328, 358, 3280, 361, 4816, 362, 2768, 364, 1744, 369, 4560, 370, 2512, 372, 1488, 376, 976, 391, 7216, 395, 6704, 397, 5680, 398, 3632, 403, 6448, 405, 5424, 406, 3376, 409, 4912, 410, 2864, 412, 1840, 419, 6320, 421, 5296, 422, 3248, 425, 4784, 426, 2736, 428, 1712, 433, 4528, 434, 2480, 436, 1456, 440, 944, 451, 6256, 453, 5232, 454, 3184, 457, 4720, 458, 2672, 460, 1648, 465, 4464, 466, 2416, 468, 1392, 472, 880, 481, 4336, 482, 2288, 484, 1264, 488, 752, 527, 7688, 535, 7432, 539, 6920, 541, 5896, 542, 3848, 551, 7304, 555, 6792, 557, 5768, 558, 3720, 563, 6536, 565, 5512, 566, 3464, 569, 5000, 570, 2952, 572, 1928, 583, 7240, 587, 6728, 589, 5704, 590, 3656, 595, 6472, 597, 5448, 598, 3400, 601, 4936, 602, 2888, 604, 1864, 611, 6344, 613, 5320, 614, 3272, 617, 4808, 618, 2760, 620, 1736, 625, 4552, 626, 2504, 628, 1480, 632, 968, 647, 7208, 651, 6696, 653, 5672, 654, 3624, 659, 6440, 661, 5416, 662, 3368, 665, 4904, 666, 2856, 668, 1832, 675, 6312, 677, 5288, 678, 3240, 681, 4776, 682, 2728, 684, 1704, 689, 4520, 690, 2472, 692, 1448, 696, 936, 707, 6248, 709, 5224, 710, 3176, 713, 4712, 714, 2664, 716, 1640, 721, 4456, 722, 2408, 724, 1384, 728, 872, 737, 4328, 738, 2280, 740, 1256, 775, 7192, 779, 6680, 781, 5656, 782, 3608, 787, 6424, 789, 5400, 790, 3352, 793, 4888, 794, 2840, 796, 1816, 803, 6296, 805, 5272, 806, 3224, 809, 4760, 810, 2712, 812, 1688, 817, 4504, 818, 2456, 820, 1432, 824, 920, 835, 6232, 837, 5208, 838, 3160, 841, 4696, 842, 2648, 844, 1624, 849, 4440, 850, 2392, 852, 1368, 865, 4312, 866, 2264, 868, 1240, 899, 6200, 901, 5176, 902, 3128, 905, 4664, 906, 2616, 908, 1592, 913, 4408, 914, 2360, 916, 1336, 929, 4280, 930, 2232, 932, 1208, 961, 4216, 962, 2168, 964, 1144, 1039, 7684, 1047, 7428, 1051, 6916, 1053, 5892, 1054, 3844, 1063, 7300, 1067, 6788, 1069, 5764, 1070, 3716, 1075, 6532, 1077, 5508, 1078, 3460, 1081, 4996, 1082, 2948, 1084, 1924, 1095, 7236, 1099, 6724, 1101, 5700, 1102, 3652, 1107, 6468, 1109, 5444, 1110, 3396, 1113, 4932, 1114, 2884, 1116, 1860, 1123, 6340, 1125, 5316, 1126, 3268, 1129, 4804, 1130, 2756, 1132, 1732, 1137, 4548, 1138, 2500, 1140, 1476, 1159, 7204, 1163, 6692, 1165, 5668, 1166, 3620, 1171, 6436, 1173, 5412, 1174, 3364, 1177, 4900, 1178, 2852, 1180, 1828, 1187, 6308, 1189, 5284, 1190, 3236, 1193, 4772, 1194, 2724, 1196, 1700, 1201, 4516, 1202, 2468, 1204, 1444, 1219, 6244, 1221, 5220, 1222, 3172, 1225, 4708, 1226, 2660, 1228, 1636, 1233, 4452, 1234, 2404, 1236, 1380, 1249, 4324, 1250, 2276, 1287, 7188, 1291, 6676, 1293, 5652, 1294, 3604, 1299, 6420, 1301, 5396, 1302, 3348, 1305, 4884, 1306, 2836, 1308, 1812, 1315, 6292, 1317, 5268, 1318, 3220, 1321, 4756, 1322, 2708, 1324, 1684, 1329, 4500, 1330, 2452, 1332, 1428, 1347, 6228, 1349, 5204, 1350, 3156, 1353, 4692, 1354, 2644, 1356, 1620, 1361, 4436, 1362, 2388, 1377, 4308, 1378, 2260, 1411, 6196, 1413, 5172, 1414, 3124, 1417, 4660, 1418, 2612, 1420, 1588, 1425, 4404, 1426, 2356, 1441, 4276, 1442, 2228, 1473, 4212, 1474, 2164, 1543, 7180, 1547, 6668, 1549, 5644, 1550, 3596, 1555, 6412, 1557, 5388, 1558, 3340, 1561, 4876, 1562, 2828, 1564, 1804, 1571, 6284, 1573, 5260, 1574, 3212, 1577, 4748, 1578, 2700, 1580, 1676, 1585, 4492, 1586, 2444, 1603, 6220, 1605, 5196, 1606, 3148, 1609, 4684, 1610, 2636, 1617, 4428, 1618, 2380, 1633, 4300, 1634, 2252, 1667, 6188, 1669, 5164, 1670, 3116, 1673, 4652, 1674, 2604, 1681, 4396, 1682, 2348, 1697, 4268, 1698, 2220, 1729, 4204, 1730, 2156, 1795, 6172, 1797, 5148, 1798, 3100, 1801, 4636, 1802, 2588, 1809, 4380, 1810, 2332, 1825, 4252, 1826, 2204, 1857, 4188, 1858, 2140, 1921, 4156, 1922, 2108, 2063, 7682, 2071, 7426, 2075, 6914, 2077, 5890, 2078, 3842, 2087, 7298, 2091, 6786, 2093, 5762, 2094, 3714, 2099, 6530, 2101, 5506, 2102, 3458, 2105, 4994, 2106, 2946, 2119, 7234, 2123, 6722, 2125, 5698, 2126, 3650, 2131, 6466, 2133, 5442, 2134, 3394, 2137, 4930, 2138, 2882, 2147, 6338, 2149, 5314, 2150, 3266, 2153, 4802, 2154, 2754, 2161, 4546, 2162, 2498, 2183, 7202, 2187, 6690, 2189, 5666, 2190, 3618, 2195, 6434, 2197, 5410, 2198, 3362, 2201, 4898, 2202, 2850, 2211, 6306, 2213, 5282, 2214, 3234, 2217, 4770, 2218, 2722, 2225, 4514, 2226, 2466, 2243, 6242, 2245, 5218, 2246, 3170, 2249, 4706, 2250, 2658, 2257, 4450, 2258, 2402, 2273, 4322, 2311, 7186, 2315, 6674, 2317, 5650, 2318, 3602, 2323, 6418, 2325, 5394, 2326, 3346, 2329, 4882, 2330, 2834, 2339, 6290, 2341, 5266, 2342, 3218, 2345, 4754, 2346, 2706, 2353, 4498, 2354, 2450, 2371, 6226, 2373, 5202, 2374, 3154, 2377, 4690, 2378, 2642, 2385, 4434, 2401, 4306, 2435, 6194, 2437, 5170, 2438, 3122, 2441, 4658, 2442, 2610, 2449, 4402, 2465, 4274, 2497, 4210, 2567, 7178, 2571, 6666, 2573, 5642, 2574, 3594, 2579, 6410, 2581, 5386, 2582, 3338, 2585, 4874, 2586, 2826, 2595, 6282, 2597, 5258, 2598, 3210, 2601, 4746, 2602, 2698, 2609, 4490, 2627, 6218, 2629, 5194, 2630, 3146, 2633, 4682, 2641, 4426, 2657, 4298, 2691, 6186, 2693, 5162, 2694, 3114, 2697, 4650, 2705, 4394, 2721, 4266, 2753, 4202, 2819, 6170, 2821, 5146, 2822, 3098, 2825, 4634, 2833, 4378, 2849, 4250, 2881, 4186, 2945, 4154, 3079, 7174, 3083, 6662, 3085, 5638, 3086, 3590, 3091, 6406, 3093, 5382, 3094, 3334, 3097, 4870, 3107, 6278, 3109, 5254, 3110, 3206, 3113, 4742, 3121, 4486, 3139, 6214, 3141, 5190, 3145, 4678, 3153, 4422, 3169, 4294, 3203, 6182, 3205, 5158, 3209, 4646, 3217, 4390, 3233, 4262, 3265, 4198, 3331, 6166, 3333, 5142, 3337, 4630, 3345, 4374, 3361, 4246, 3393, 4182, 3457, 4150, 3587, 6158, 3589, 5134, 3593, 4622, 3601, 4366, 3617, 4238, 3649, 4174, 3713, 4142, 3841, 4126, 4111, 7681, 4119, 7425, 4123, 6913, 4125, 5889, 4135, 7297, 4139, 6785, 4141, 5761, 4147, 6529, 4149, 5505, 4153, 4993, 4167, 7233, 4171, 6721, 4173, 5697, 4179, 6465, 4181, 5441, 4185, 4929, 4195, 6337, 4197, 5313, 4201, 4801, 4209, 4545, 4231, 7201, 4235, 6689, 4237, 5665, 4243, 6433, 4245, 5409, 4249, 4897, 4259, 6305, 4261, 5281, 4265, 4769, 4273, 4513, 4291, 6241, 4293, 5217, 4297, 4705, 4305, 4449, 4359, 7185, 4363, 6673, 4365, 5649, 4371, 6417, 4373, 5393, 4377, 4881, 4387, 6289, 4389, 5265, 4393, 4753, 4401, 4497, 4419, 6225, 4421, 5201, 4425, 4689, 4483, 6193, 4485, 5169, 4489, 4657, 4615, 7177, 4619, 6665, 4621, 5641, 4627, 6409, 4629, 5385, 4633, 4873, 4643, 6281, 4645, 5257, 4649, 4745, 4675, 6217, 4677, 5193, 4739, 6185, 4741, 5161, 4867, 6169, 4869, 5145, 5127, 7173, 5131, 6661, 5133, 5637, 5139, 6405, 5141, 5381, 5155, 6277, 5157, 5253, 5187, 6213, 5251, 6181, 5379, 6165, 5635, 6157, 6151, 7171, 6155, 6659, 6163, 6403, 6179, 6275, 6211, 5189, 4681, 4433, 4321, 3142, 2634, 2386, 2274, 1612, 1364, 1252, 856, 744, 496}; - ushort[] table2 = {3, 6144, 5, 5120, 6, 3072, 9, 4608, 10, 2560, 12, 1536, 17, 4352, 18, 2304, 20, 1280, 24, 768, 33, 4224, 34, 2176, 36, 1152, 40, 640, 48, 384, 65, 4160, 66, 2112, 68, 1088, 72, 576, 80, 320, 96, 192, 129, 4128, 130, 2080, 132, 1056, 136, 544, 144, 288, 257, 4112, 258, 2064, 260, 1040, 264, 528, 513, 4104, 514, 2056, 516, 1032, 1025, 4100, 1026, 2052, 2049, 4098, 4097, 2050, 1028, 520, 272, 160}; - - // create tables to check decFcsChars - table1Check = new Dictionary(2000); - table2Check = new Dictionary(200); - for (int k = 0; k < table1.Length; k++) - table1Check.Add(table1[k], k); - for (int k = 0; k < table2.Length; k++) - table2Check.Add(table2[k], k); - } - - protected override Result doDecode(BinaryBitmap image, IDictionary hints) - { - currentBitmap = image; - return base.doDecode(image, hints); - } - - public override void reset() - { - base.reset(); - currentBitmap = null; - } - - private ushort binaryStringToDec(string binary) - { - ushort factor = (ushort) Math.Pow(2, binary.Length - 1); - ushort result = 0; - - foreach (char bit in binary) - { - if (bit == '1') - result += factor; - - factor /= 2; - } - - return result; - } - - private string invertedBinaryString(string binary) - { - string result = ""; - - foreach (char bit in binary) - { - if (bit == '1') - result += '0'; - else - result += '1'; - } - - return result; - } - - private bool getCodeWords(out int[] codeWord, string imb, IDictionary table1Check, IDictionary table2Check, int[][] barPos, char[][] barType) - { - // initialize the binaryFcsChars to 0 (has 13 bits) - StringBuilder[] binaryFcsChars = new StringBuilder[10]; - for (int c = 0; c < 10; c++) - binaryFcsChars[c] = new StringBuilder("0000000000000"); - - // fill in the binaryFcsChars - for (int pos = 0; pos < 65; pos++) - { - if (imb[pos] != 'D' && imb[pos] != 'A' && imb[pos] != 'F') - continue; - - int offset = pos + 1; - for (int a = 0; a < 10; a++) // int[][] barPos - { - int i; - for (i = 0; i < 13; i++) - { - if (barPos[a][i] == offset) - { - if (barType[a][i] == imb[pos] || imb[pos] == 'F') - binaryFcsChars[a][12 - i] = '1'; - } - } - } - } - - // convert each binaryFcsChar into decimal format - ushort[] decFcsChars = new ushort[10]; - for (int k = 0; k < 10; k++) - decFcsChars[k] = binaryStringToDec(binaryFcsChars[k].ToString()); - - // change decFcsChars according to whether FCS rules (whether it is the decFcsChars value is contained in one of the tables) - for (int k = 0; k < decFcsChars.Length; k++) - { - if (!table1Check.ContainsKey(decFcsChars[k]) && !table2Check.ContainsKey(decFcsChars[k])) - { - binaryFcsChars[k].Replace(binaryFcsChars[k].ToString(), invertedBinaryString(binaryFcsChars[k].ToString())); - decFcsChars[k] = binaryStringToDec(binaryFcsChars[k].ToString()); - } - } - - // get codewords A-J - codeWord = new int[10]; - for (int k = 0; k < 10; k++) - { - if (!table1Check.ContainsKey(decFcsChars[k])) - { - if (table2Check.ContainsKey(decFcsChars[k])) - codeWord[k] = table2Check[decFcsChars[k]] + 1287; - else - return false; // invert the imb - } - else - codeWord[k] = table1Check[decFcsChars[k]]; - } - - return true; - } - - private string getTrackingNumber(string imb) - { - - // get codewords A-J - int[] codeWord; - if (!getCodeWords(out codeWord, imb, table1Check, table2Check, barPos, barType)) - { - // imb is upside down - StringBuilder invertedImb = new StringBuilder(imb.Length); - for (int k = imb.Length - 1; k >= 0; k--) - { - if (imb[k] == 'A') - invertedImb.Append('D'); - else if (imb[k] == 'D') - invertedImb.Append('A'); - else - invertedImb.Append(imb[k]); - } - - if (!getCodeWords(out codeWord, invertedImb.ToString(), table1Check, table2Check, barPos, barType)) - return null; - } - - - if (codeWord[A] > 658) - codeWord[A] -= 659; - codeWord[J] /= 2; - - // codewords to binaryData - BigInteger binaryData = codeWord[A]; - for (int k = 1; k <= 8; k++) - binaryData = (binaryData*1365) + codeWord[k]; - binaryData = (binaryData*636) + codeWord[J]; - - // get tracking code - int[] tCode = new int[20]; - for (int i = 19; i >= 2; i--) - { - tCode[i] = (int) (binaryData%10); - binaryData /= 10; - } - tCode[1] = (int) (binaryData%5); - binaryData /= 5; - tCode[0] = (int) (binaryData%10); - binaryData /= 10; - - // get routing code and imb number - string imbTrackingNumber = ""; - foreach (int t in tCode) - imbTrackingNumber += t.ToString(); - ulong rCode; - if (binaryData > 1000000000) - { - rCode = (ulong) (binaryData - 1000000000 - 100000 - 1); - imbTrackingNumber += rCode.ToString().PadLeft(11, '0'); - } - else if (binaryData > 100000) - { - rCode = (ulong) (binaryData - 100000 - 1); - imbTrackingNumber += rCode.ToString().PadLeft(9, '0'); - } - else if (binaryData > 0) - { - rCode = (ulong) (binaryData - 1); - imbTrackingNumber += rCode.ToString().PadLeft(5, '0'); - } - - return imbTrackingNumber; - } - - private void fillLists(BitArray row, BitArray topRow, BitArray botRow, ref List listRow, ref List listTop, ref List listBot, int start, int stop) // list: 1=black 0=white - { - const bool isWhite = false; - bool insideBar = false; - - for (int i = start; i <= stop; i++) - { - if (row[i] ^ isWhite) // if current pixel is black - { - if (!insideBar) - { - insideBar = true; - - listRow.Add(1); - - if (topRow[i] ^ isWhite) - listTop.Add(1); - else - listTop.Add(0); - - if (botRow[i] ^ isWhite) - listBot.Add(1); - else - listBot.Add(0); - } - } - else // if current pixel is white - { - if (insideBar) - { - listRow.Add(0); - - if (topRow[i] ^ isWhite) - listTop.Add(1); - else - listTop.Add(0); - - if (botRow[i] ^ isWhite) - listBot.Add(1); - else - listBot.Add(0); - } - - insideBar = false; - } - } - } - - private int isIMB(BitArray row, ref int pixelStartOffset, ref int pixelStopOffset, ref int pixelBarLength) - { - int width = row.Size; - int rowOffset = row.getNextSet(0); - pixelStartOffset = rowOffset; - int previousPixelOffset = pixelStartOffset; - const bool isWhite = false; - - int countBars = 0; - bool insideBar = false; - int currBarLength = 0; - int prevBarLength = 0; - - bool insideWS = false; - int numWSBetween = 0; - int currWSLength = 0; - int prevWSLength = 0; - - for (int i = rowOffset; i < width; i++) - { - if (row[i] ^ isWhite) // if current pixel is black - { - insideWS = false; - - if (!insideBar) - { - if (countBars <= 1) - { - prevWSLength = currWSLength; - } - else - { - if (prevWSLength != currWSLength) - { - numWSBetween = 1; - prevWSLength = currWSLength; - countBars = 1; - pixelStartOffset = previousPixelOffset; - } - } - countBars++; - - insideBar = true; - previousPixelOffset = i; - } - - currWSLength = 0; - - currBarLength++; - } - else // if current pixel is white - { - insideBar = false; - - if (!insideWS) - { - numWSBetween++; - insideWS = true; - - if (countBars <= 1) - prevBarLength = currBarLength; - else - { - if (prevBarLength != currBarLength) - { - countBars = 1; - numWSBetween = 1; - prevWSLength = 0; - pixelStartOffset = previousPixelOffset; - prevBarLength = currBarLength; - } - else - { - if (countBars == 65) // made it this far, so break - { - pixelStopOffset = i; - //pixelBarLength = prevBarLength; - break; - } - } - } - currBarLength = 0; - } - - - currWSLength++; - } - - - } - - pixelBarLength = prevBarLength; - return (countBars); - } - - private int getNumberBars(BitArray row, int start, int stop, int barWidth) - { - const bool isWhite = false; - bool insideBar = false; - int countBars = 0; - int currentBarWidth = 0; - - for (int i = start; i <= stop; i++) - { - if (row[i] ^ isWhite) // if current pixel is black - { - if (!insideBar) - { - //countBars++; - insideBar = true; - } - currentBarWidth++; - - if (i == stop) - { - if (currentBarWidth == barWidth) - countBars++; - } - } - else // if current pixel is white - { - if (insideBar) - { - if (currentBarWidth == barWidth) - countBars++; - } - insideBar = false; - currentBarWidth = 0; - } - } - - return countBars; - } - - public override Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - if (currentBitmap == null) - return null; - - int pixelStartOffset = 0; - int pixelStopOffset = currentBitmap.Width - 1; - int pixelBarLength = 0; - int numBars = isIMB(row, ref pixelStartOffset, ref pixelStopOffset, ref pixelBarLength); - if (numBars != NUM_BARS_IMB) - return null; - - // create the two bitarrays to check top and bottom - BitArray topRow = new BitArray(currentBitmap.Width); - BitArray botRow = new BitArray(currentBitmap.Width); - int rowNumberTop = rowNumber; - int rowNumberBot = rowNumber; - - do - { - if (rowNumberTop <= 0) - return null; - rowNumberTop--; - topRow = currentBitmap.getBlackRow(rowNumberTop, topRow); - } while (getNumberBars(topRow, pixelStartOffset, pixelStopOffset, pixelBarLength) >= NUM_BARS_IMB); - do - { - if (rowNumberBot >= (currentBitmap.Height - 1)) - return null; - rowNumberBot++; - botRow = currentBitmap.getBlackRow(rowNumberBot, botRow); - } while (getNumberBars(botRow, pixelStartOffset, pixelStopOffset, pixelBarLength) >= NUM_BARS_IMB); - - List listRow = new List(); - List listTop = new List(); - List listBot = new List(); - fillLists(row, topRow, botRow, ref listRow, ref listTop, ref listBot, pixelStartOffset, pixelStopOffset); - - string symbolCode = ""; - for (int k = 0; k < listRow.Count; k++) - { - if (listRow[k] == 0) - continue; - - if (listBot[k] == 1 && listTop[k] == 1) - symbolCode += "F"; - else if (listBot[k] == 1) - symbolCode += "D"; - else if (listTop[k] == 1) - symbolCode += "A"; - else - symbolCode += "T"; - } - - string trackingNumber = getTrackingNumber(symbolCode); - if (trackingNumber == null) - return null; - - var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) - ? null - : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint(pixelStartOffset, rowNumber)); - resultPointCallback(new ResultPoint(pixelStopOffset, rowNumber)); - } - - return new Result( - trackingNumber, - null, - new[] - { - new ResultPoint(pixelStartOffset, rowNumber), - new ResultPoint(pixelStopOffset, rowNumber) - }, - BarcodeFormat.IMB); - } - } -} diff --git a/zxing.core/xx/maxicode/MaxiCodeReader.cs b/zxing.core/xx/maxicode/MaxiCodeReader.cs deleted file mode 100644 index c9cfbe4..0000000 --- a/zxing.core/xx/maxicode/MaxiCodeReader.cs +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Maxicode.Internal; - -namespace ZXing.Maxicode -{ - /// - /// This implementation can detect and decode a MaxiCode in an image. - /// - public sealed class MaxiCodeReader : Reader - { - private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0]; - private const int MATRIX_WIDTH = 30; - private const int MATRIX_HEIGHT = 33; - - private readonly Decoder decoder = new Decoder(); - - /// - /// Locates and decodes a MaxiCode in an image. - /// - /// a String representing the content encoded by the MaxiCode - /// if a MaxiCode cannot be decoded - /// - public Result decode(BinaryBitmap image) - { - return decode(image, null); - } - - /// - /// Locates and decodes a MaxiCode within an image. This method also accepts - /// hints, each possibly associated to some data, which may help the implementation decode. - /// - /// image of barcode to decode - /// passed as a from - /// to arbitrary data. The - /// meaning of the data depends upon the hint type. The implementation may or may not do - /// anything with these hints. - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image, IDictionary hints) - { - DecoderResult decoderResult; - if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) - { - BitMatrix bits = extractPureBits(image.BlackMatrix); - if (bits == null) - return null; - decoderResult = decoder.decode(bits, hints); - if (decoderResult == null) - return null; - } - else - { - return null; - } - - ResultPoint[] points = NO_POINTS; - Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.MAXICODE); - - var ecLevel = decoderResult.ECLevel; - if (ecLevel != null) - { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - return result; - } - - public void reset() - { - // do nothing - } - - /// - /// This method detects a code in a "pure" image -- that is, pure monochrome image - /// which contains only an unrotated, unskewed, image of a code, with some white border - /// around it. This is a specialized method that works exceptionally fast in this special - /// case. - /// - /// - /// - /// - private static BitMatrix extractPureBits(BitMatrix image) - { - - int[] enclosingRectangle = image.getEnclosingRectangle(); - if (enclosingRectangle == null) - { - return null; - } - - int left = enclosingRectangle[0]; - int top = enclosingRectangle[1]; - int width = enclosingRectangle[2]; - int height = enclosingRectangle[3]; - - // Now just read off the bits - BitMatrix bits = new BitMatrix(MATRIX_WIDTH, MATRIX_HEIGHT); - for (int y = 0; y < MATRIX_HEIGHT; y++) - { - int iy = top + (y * height + height / 2) / MATRIX_HEIGHT; - for (int x = 0; x < MATRIX_WIDTH; x++) - { - int ix = left + (x * width + width / 2 + (y & 0x01) * width / 2) / MATRIX_WIDTH; - if (image[ix, iy]) - { - bits[x, y] = true; - } - } - } - return bits; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/maxicode/decoder/BitMatrixParser.cs b/zxing.core/xx/maxicode/decoder/BitMatrixParser.cs deleted file mode 100644 index 9d7723c..0000000 --- a/zxing.core/xx/maxicode/decoder/BitMatrixParser.cs +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2011 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 ZXing.Common; - -namespace ZXing.Maxicode.Internal -{ - /// - /// mike32767 - /// Manuel Kasten - /// - sealed class BitMatrixParser - { - private static readonly int[][] BITNR = new int[][] { - new[] {121,120,127,126,133,132,139,138,145,144,151,150,157,156,163,162,169,168,175,174,181,180,187,186,193,192,199,198, -2, -2}, - new[] {123,122,129,128,135,134,141,140,147,146,153,152,159,158,165,164,171,170,177,176,183,182,189,188,195,194,201,200,816, -3}, - new[] {125,124,131,130,137,136,143,142,149,148,155,154,161,160,167,166,173,172,179,178,185,184,191,190,197,196,203,202,818,817}, - new[] {283,282,277,276,271,270,265,264,259,258,253,252,247,246,241,240,235,234,229,228,223,222,217,216,211,210,205,204,819, -3}, - new[] {285,284,279,278,273,272,267,266,261,260,255,254,249,248,243,242,237,236,231,230,225,224,219,218,213,212,207,206,821,820}, - new[] {287,286,281,280,275,274,269,268,263,262,257,256,251,250,245,244,239,238,233,232,227,226,221,220,215,214,209,208,822, -3}, - new[] {289,288,295,294,301,300,307,306,313,312,319,318,325,324,331,330,337,336,343,342,349,348,355,354,361,360,367,366,824,823}, - new[] {291,290,297,296,303,302,309,308,315,314,321,320,327,326,333,332,339,338,345,344,351,350,357,356,363,362,369,368,825, -3}, - new[] {293,292,299,298,305,304,311,310,317,316,323,322,329,328,335,334,341,340,347,346,353,352,359,358,365,364,371,370,827,826}, - new[] {409,408,403,402,397,396,391,390, 79, 78, -2, -2, 13, 12, 37, 36, 2, -1, 44, 43,109,108,385,384,379,378,373,372,828, -3}, - new[] {411,410,405,404,399,398,393,392, 81, 80, 40, -2, 15, 14, 39, 38, 3, -1, -1, 45,111,110,387,386,381,380,375,374,830,829}, - new[] {413,412,407,406,401,400,395,394, 83, 82, 41, -3, -3, -3, -3, -3, 5, 4, 47, 46,113,112,389,388,383,382,377,376,831, -3}, - new[] {415,414,421,420,427,426,103,102, 55, 54, 16, -3, -3, -3, -3, -3, -3, -3, 20, 19, 85, 84,433,432,439,438,445,444,833,832}, - new[] {417,416,423,422,429,428,105,104, 57, 56, -3, -3, -3, -3, -3, -3, -3, -3, 22, 21, 87, 86,435,434,441,440,447,446,834, -3}, - new[] {419,418,425,424,431,430,107,106, 59, 58, -3, -3, -3, -3, -3, -3, -3, -3, -3, 23, 89, 88,437,436,443,442,449,448,836,835}, - new[] {481,480,475,474,469,468, 48, -2, 30, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 0, 53, 52,463,462,457,456,451,450,837, -3}, - new[] {483,482,477,476,471,470, 49, -1, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -1,465,464,459,458,453,452,839,838}, - new[] {485,484,479,478,473,472, 51, 50, 31, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 1, -2, 42,467,466,461,460,455,454,840, -3}, - new[] {487,486,493,492,499,498, 97, 96, 61, 60, -3, -3, -3, -3, -3, -3, -3, -3, -3, 26, 91, 90,505,504,511,510,517,516,842,841}, - new[] {489,488,495,494,501,500, 99, 98, 63, 62, -3, -3, -3, -3, -3, -3, -3, -3, 28, 27, 93, 92,507,506,513,512,519,518,843, -3}, - new[] {491,490,497,496,503,502,101,100, 65, 64, 17, -3, -3, -3, -3, -3, -3, -3, 18, 29, 95, 94,509,508,515,514,521,520,845,844}, - new[] {559,558,553,552,547,546,541,540, 73, 72, 32, -3, -3, -3, -3, -3, -3, 10, 67, 66,115,114,535,534,529,528,523,522,846, -3}, - new[] {561,560,555,554,549,548,543,542, 75, 74, -2, -1, 7, 6, 35, 34, 11, -2, 69, 68,117,116,537,536,531,530,525,524,848,847}, - new[] {563,562,557,556,551,550,545,544, 77, 76, -2, 33, 9, 8, 25, 24, -1, -2, 71, 70,119,118,539,538,533,532,527,526,849, -3}, - new[] {565,564,571,570,577,576,583,582,589,588,595,594,601,600,607,606,613,612,619,618,625,624,631,630,637,636,643,642,851,850}, - new[] {567,566,573,572,579,578,585,584,591,590,597,596,603,602,609,608,615,614,621,620,627,626,633,632,639,638,645,644,852, -3}, - new[] {569,568,575,574,581,580,587,586,593,592,599,598,605,604,611,610,617,616,623,622,629,628,635,634,641,640,647,646,854,853}, - new[] {727,726,721,720,715,714,709,708,703,702,697,696,691,690,685,684,679,678,673,672,667,666,661,660,655,654,649,648,855, -3}, - new[] {729,728,723,722,717,716,711,710,705,704,699,698,693,692,687,686,681,680,675,674,669,668,663,662,657,656,651,650,857,856}, - new[] {731,730,725,724,719,718,713,712,707,706,701,700,695,694,689,688,683,682,677,676,671,670,665,664,659,658,653,652,858, -3}, - new[] {733,732,739,738,745,744,751,750,757,756,763,762,769,768,775,774,781,780,787,786,793,792,799,798,805,804,811,810,860,859}, - new[] {735,734,741,740,747,746,753,752,759,758,765,764,771,770,777,776,783,782,789,788,795,794,801,800,807,806,813,812,861, -3}, - new[] {737,736,743,742,749,748,755,754,761,760,767,766,773,772,779,778,785,784,791,790,797,796,803,802,809,808,815,814,863,862} - }; - - private readonly BitMatrix bitMatrix; - - /// - /// to parse - /// - internal BitMatrixParser(BitMatrix bitMatrix) - { - this.bitMatrix = bitMatrix; - } - - internal byte[] readCodewords() - { - byte[] result = new byte[144]; - int height = bitMatrix.Height; - int width = bitMatrix.Width; - for (int y = 0; y < height; y++) - { - int[] bitnrRow = BITNR[y]; - for (int x = 0; x < width; x++) - { - int bit = bitnrRow[x]; - if (bit >= 0 && bitMatrix[x, y]) - { - result[bit / 6] |= (byte)(1 << (5 - (bit % 6))); - } - } - } - return result; - } - } -} diff --git a/zxing.core/xx/maxicode/decoder/DecodedBitStreamParser.cs b/zxing.core/xx/maxicode/decoder/DecodedBitStreamParser.cs deleted file mode 100644 index c991898..0000000 --- a/zxing.core/xx/maxicode/decoder/DecodedBitStreamParser.cs +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2011 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.Text; -using ZXing.QrCode.Internal; -using ZXing.Common; - -namespace ZXing.Maxicode.Internal -{ - /// - ///

MaxiCodes can encode text or structured information as bits in one of several modes, - /// with multiple character sets in one code. This class decodes the bits back into text.

- /// - /// mike32767 - /// Manuel Kasten - ///
- internal static class DecodedBitStreamParser - { - private const char SHIFTA = '\uFFF0'; - private const char SHIFTB = '\uFFF1'; - private const char SHIFTC = '\uFFF2'; - private const char SHIFTD = '\uFFF3'; - private const char SHIFTE = '\uFFF4'; - private const char TWOSHIFTA = '\uFFF5'; - private const char THREESHIFTA = '\uFFF6'; - private const char LATCHA = '\uFFF7'; - private const char LATCHB = '\uFFF8'; - private const char LOCK = '\uFFF9'; - private const char ECI = '\uFFFA'; - private const char NS = '\uFFFB'; - private const char PAD = '\uFFFC'; - private const char FS = '\u001C'; - private const char GS = '\u001D'; - private const char RS = '\u001E'; - private const string NINE_DIGITS = "000000000"; - private const string THREE_DIGITS = "000"; - - private static String[] SETS = { - "\nABCDEFGHIJKLMNOPQRSTUVWXYZ"+ECI+FS+GS+RS+NS+' '+PAD+"\"#$%&'()*+,-./0123456789:"+SHIFTB+SHIFTC+SHIFTD+SHIFTE+LATCHB, - "`abcdefghijklmnopqrstuvwxyz"+ECI+FS+GS+RS+NS+'{'+PAD+"}~\u007F;<=>?[\\]^_ ,./:@!|"+PAD+TWOSHIFTA+THREESHIFTA+PAD+SHIFTA+SHIFTC+SHIFTD+SHIFTE+LATCHA, - "\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA"+ECI+FS+GS+RS+"\u00DB\u00DC\u00DD\u00DE\u00DF\u00AA\u00AC\u00B1\u00B2\u00B3\u00B5\u00B9\u00BA\u00BC\u00BD\u00BE\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089"+LATCHA+' '+LOCK+SHIFTD+SHIFTE+LATCHB, - "\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA"+ECI+FS+GS+RS+NS+"\u00FB\u00FC\u00FD\u00FE\u00FF\u00A1\u00A8\u00AB\u00AF\u00B0\u00B4\u00B7\u00B8\u00BB\u00BF\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094"+LATCHA+' '+SHIFTC+LOCK+SHIFTE+LATCHB, - "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\n\u000B\u000C\r\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A"+ECI+PAD+PAD+'\u001B'+NS+FS+GS+RS+"\u001F\u009F\u00A0\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A9\u00AD\u00AE\u00B6\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E"+LATCHA+' '+SHIFTC+SHIFTD+LOCK+LATCHB, - "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\n\u000B\u000C\r\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\u0020\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B\u003C\u003D\u003E\u003F" - }; - - internal static DecoderResult decode(byte[] bytes, int mode) - { - StringBuilder result = new StringBuilder(144); - switch (mode) - { - case 2: - case 3: - String postcode; - if (mode == 2) - { - int pc = getPostCode2(bytes); - var df = "0000000000".Substring(0, getPostCode2Length(bytes)); - postcode = pc.ToString(df); - } - else - { - postcode = getPostCode3(bytes); - } - String country = getCountry(bytes).ToString(THREE_DIGITS); - String service = getServiceClass(bytes).ToString(THREE_DIGITS); - result.Append(getMessage(bytes, 10, 84)); - if (result.ToString().StartsWith("[)>" + RS + "01" + GS)) - { - result.Insert(9, postcode + GS + country + GS + service + GS); - } - else - { - result.Insert(0, postcode + GS + country + GS + service + GS); - } - break; - case 4: - result.Append(getMessage(bytes, 1, 93)); - break; - case 5: - result.Append(getMessage(bytes, 1, 77)); - break; - } - - return new DecoderResult(bytes, result.ToString(), null, mode.ToString()); - } - - private static int getBit(int bit, byte[] bytes) - { - bit--; - return (bytes[bit / 6] & (1 << (5 - (bit % 6)))) == 0 ? 0 : 1; - } - - private static int getInt(byte[] bytes, byte[] x) - { - if (x.Length == 0) - throw new ArgumentException("x"); - - int val = 0; - for (int i = 0; i < x.Length; i++) - { - val += getBit(x[i], bytes) << (x.Length - i - 1); - } - return val; - } - - private static int getCountry(byte[] bytes) - { - return getInt(bytes, new byte[] { 53, 54, 43, 44, 45, 46, 47, 48, 37, 38 }); - } - - private static int getServiceClass(byte[] bytes) - { - return getInt(bytes, new byte[] { 55, 56, 57, 58, 59, 60, 49, 50, 51, 52 }); - } - - private static int getPostCode2Length(byte[] bytes) - { - return getInt(bytes, new byte[] { 39, 40, 41, 42, 31, 32 }); - } - - private static int getPostCode2(byte[] bytes) - { - return getInt(bytes, new byte[] {33, 34, 35, 36, 25, 26, 27, 28, 29, 30, 19, - 20, 21, 22, 23, 24, 13, 14, 15, 16, 17, 18, 7, 8, 9, 10, 11, 12, 1, 2}); - } - - private static String getPostCode3(byte[] bytes) - { - return new String( - new char[] - { - SETS[0][getInt(bytes, new byte[] {39, 40, 41, 42, 31, 32})], - SETS[0][getInt(bytes, new byte[] {33, 34, 35, 36, 25, 26})], - SETS[0][getInt(bytes, new byte[] {27, 28, 29, 30, 19, 20})], - SETS[0][getInt(bytes, new byte[] {21, 22, 23, 24, 13, 14})], - SETS[0][getInt(bytes, new byte[] {15, 16, 17, 18, 7, 8})], - SETS[0][getInt(bytes, new byte[] {9, 10, 11, 12, 1, 2})], - } - ); - } - - private static String getMessage(byte[] bytes, int start, int len) - { - StringBuilder sb = new StringBuilder(); - int shift = -1; - int set = 0; - int lastset = 0; - for (int i = start; i < start + len; i++) - { - char c = SETS[set][bytes[i]]; - switch (c) - { - case LATCHA: - set = 0; - shift = -1; - break; - case LATCHB: - set = 1; - shift = -1; - break; - case SHIFTA: - case SHIFTB: - case SHIFTC: - case SHIFTD: - case SHIFTE: - lastset = set; - set = c - SHIFTA; - shift = 1; - break; - case TWOSHIFTA: - lastset = set; - set = 0; - shift = 2; - break; - case THREESHIFTA: - lastset = set; - set = 0; - shift = 3; - break; - case NS: - int nsval = (bytes[++i] << 24) + (bytes[++i] << 18) + (bytes[++i] << 12) + (bytes[++i] << 6) + bytes[++i]; - sb.Append(nsval.ToString(NINE_DIGITS)); - break; - case LOCK: - shift = -1; - break; - default: - sb.Append(c); - break; - } - if (shift-- == 0) - { - set = lastset; - } - } - while (sb.Length > 0 && sb[sb.Length - 1] == PAD) - { - sb.Length = sb.Length - 1; - } - return sb.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/maxicode/decoder/Decoder.cs b/zxing.core/xx/maxicode/decoder/Decoder.cs deleted file mode 100644 index 9d02680..0000000 --- a/zxing.core/xx/maxicode/decoder/Decoder.cs +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; -using ZXing.Common.ReedSolomon; - -namespace ZXing.Maxicode.Internal -{ - /// - ///

The main class which implements MaxiCode decoding -- as opposed to locating and extracting - /// the MaxiCode from an image.

- /// - /// Manuel Kasten - ///
- public sealed class Decoder - { - private const int ALL = 0; - private const int EVEN = 1; - private const int ODD = 2; - - private readonly ReedSolomonDecoder rsDecoder; - - public Decoder() - { - rsDecoder = new ReedSolomonDecoder(GenericGF.MAXICODE_FIELD_64); - } - - public DecoderResult decode(BitMatrix bits) - { - return decode(bits, null); - } - - public DecoderResult decode(BitMatrix bits, - IDictionary hints) - { - BitMatrixParser parser = new BitMatrixParser(bits); - byte[] codewords = parser.readCodewords(); - - if (!correctErrors(codewords, 0, 10, 10, ALL)) - return null; - - int mode = codewords[0] & 0x0F; - byte[] datawords; - switch (mode) - { - case 2: - case 3: - case 4: - if (!correctErrors(codewords, 20, 84, 40, EVEN)) - return null; - if (!correctErrors(codewords, 20, 84, 40, ODD)) - return null; - datawords = new byte[94]; - break; - case 5: - if (!correctErrors(codewords, 20, 68, 56, EVEN)) - return null; - if (!correctErrors(codewords, 20, 68, 56, ODD)) - return null; - datawords = new byte[78]; - break; - default: - return null; - } - - Array.Copy(codewords, 0, datawords, 0, 10); - Array.Copy(codewords, 20, datawords, 10, datawords.Length - 10); - - return DecodedBitStreamParser.decode(datawords, mode); - } - - private bool correctErrors(byte[] codewordBytes, - int start, - int dataCodewords, - int ecCodewords, - int mode) - { - int codewords = dataCodewords + ecCodewords; - - // in EVEN or ODD mode only half the codewords - int divisor = mode == ALL ? 1 : 2; - - // First read into an array of ints - int[] codewordsInts = new int[codewords / divisor]; - for (int i = 0; i < codewords; i++) - { - if ((mode == ALL) || (i % 2 == (mode - 1))) - { - codewordsInts[i / divisor] = codewordBytes[i + start] & 0xFF; - } - } - - if (!rsDecoder.decode(codewordsInts, ecCodewords / divisor)) - return false; - - // Copy back into array of bytes -- only need to worry about the bytes that were data - // We don't care about errors in the error-correction codewords - for (int i = 0; i < dataCodewords; i++) - { - if ((mode == ALL) || (i % 2 == (mode - 1))) - { - codewordBytes[i + start] = (byte)codewordsInts[i / divisor]; - } - } - - return true; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/multi/ByQuadrantReader.cs b/zxing.core/xx/multi/ByQuadrantReader.cs deleted file mode 100644 index fdf3215..0000000 --- a/zxing.core/xx/multi/ByQuadrantReader.cs +++ /dev/null @@ -1,128 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Collections.Generic; - -namespace ZXing.Multi -{ - /// - /// This class attempts to decode a barcode from an image, not by scanning the whole image, - /// but by scanning subsets of the image. This is important when there may be multiple barcodes in - /// an image, and detecting a barcode may find parts of multiple barcode and fail to decode - /// (e.g. QR Codes). Instead this scans the four quadrants of the image -- and also the center - /// 'quadrant' to cover the case where a barcode is found in the center. - /// - /// - public sealed class ByQuadrantReader : Reader - { - private readonly Reader @delegate; - - /// - /// Initializes a new instance of the class. - /// - /// The @delegate. - public ByQuadrantReader(Reader @delegate) - { - this.@delegate = @delegate; - } - - /// - /// Locates and decodes a barcode in some format within an image. - /// - /// image of barcode to decode - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image) - { - return decode(image, null); - } - - /// - /// Locates and decodes a barcode in some format within an image. This method also accepts - /// hints, each possibly associated to some data, which may help the implementation decode. - /// - /// image of barcode to decode - /// passed as a from - /// to arbitrary data. The - /// meaning of the data depends upon the hint type. The implementation may or may not do - /// anything with these hints. - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image, IDictionary hints) - { - int width = image.Width; - int height = image.Height; - int halfWidth = width/2; - int halfHeight = height/2; - - // No need to call makeAbsolute as results will be relative to original top left here - var result = @delegate.decode(image.crop(0, 0, halfWidth, halfHeight), hints); - if (result != null) - return result; - - result = @delegate.decode(image.crop(halfWidth, 0, halfWidth, halfHeight), hints); - if (result != null) - { - makeAbsolute(result.ResultPoints, halfWidth, 0); - return result; - } - - result = @delegate.decode(image.crop(0, halfHeight, halfWidth, halfHeight), hints); - if (result != null) - { - makeAbsolute(result.ResultPoints, 0, halfHeight); - return result; - } - - result = @delegate.decode(image.crop(halfWidth, halfHeight, halfWidth, halfHeight), hints); - if (result != null) - { - makeAbsolute(result.ResultPoints, halfWidth, halfHeight); - return result; - } - - int quarterWidth = halfWidth/2; - int quarterHeight = halfHeight/2; - var center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight); - result = @delegate.decode(center, hints); - makeAbsolute(result.ResultPoints, quarterWidth, quarterHeight); - return result; - } - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - public void reset() - { - @delegate.reset(); - } - - private static void makeAbsolute(ResultPoint[] points, int leftOffset, int topOffset) - { - if (points != null) - { - for (int i = 0; i < points.Length; i++) - { - ResultPoint relative = points[i]; - points[i] = new ResultPoint(relative.X + leftOffset, relative.Y + topOffset); - } - } - } - } -} diff --git a/zxing.core/xx/multi/GenericMultipleBarcodeReader.cs b/zxing.core/xx/multi/GenericMultipleBarcodeReader.cs deleted file mode 100644 index 0013ab4..0000000 --- a/zxing.core/xx/multi/GenericMultipleBarcodeReader.cs +++ /dev/null @@ -1,222 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Collections.Generic; - -namespace ZXing.Multi -{ - /// - ///

Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image. - /// After one barcode is found, the areas left, above, right and below the barcode's - /// {@link com.google.zxing.ResultPoint}s are scanned, recursively.

- ///

A caller may want to also employ {@link ByQuadrantReader} when attempting to find multiple - /// 2D barcodes, like QR Codes, in an image, where the presence of multiple barcodes might prevent - /// detecting any one of them.

- ///

That is, instead of passing a {@link Reader} a caller might pass - /// new ByQuadrantReader(reader).

- /// Sean Owen - ///
- public sealed class GenericMultipleBarcodeReader : MultipleBarcodeReader, Reader - { - private const int MIN_DIMENSION_TO_RECUR = 30; - private const int MAX_DEPTH = 4; - - private readonly Reader _delegate; - - /// - /// Initializes a new instance of the class. - /// - /// The @delegate. - public GenericMultipleBarcodeReader(Reader @delegate) - { - this._delegate = @delegate; - } - - /// - /// Decodes the multiple. - /// - /// The image. - /// - public Result[] decodeMultiple(BinaryBitmap image) - { - return decodeMultiple(image, null); - } - - /// - /// Decodes the multiple. - /// - /// The image. - /// The hints. - /// - public Result[] decodeMultiple(BinaryBitmap image, IDictionary hints) - { - var results = new List(); - doDecodeMultiple(image, hints, results, 0, 0, 0); - if ((results.Count == 0)) - { - return null; - } - int numResults = results.Count; - Result[] resultArray = new Result[numResults]; - for (int i = 0; i < numResults; i++) - { - resultArray[i] = (Result)results[i]; - } - return resultArray; - } - - private void doDecodeMultiple(BinaryBitmap image, IDictionary hints, IList results, int xOffset, int yOffset, int currentDepth) - { - if (currentDepth > MAX_DEPTH) - { - return; - } - - Result result = _delegate.decode(image, hints); - if (result == null) - return; - - bool alreadyFound = false; - for (int i = 0; i < results.Count; i++) - { - Result existingResult = (Result)results[i]; - if (existingResult.Text.Equals(result.Text)) - { - alreadyFound = true; - break; - } - } - if (!alreadyFound) - { - results.Add(translateResultPoints(result, xOffset, yOffset)); - } - - ResultPoint[] resultPoints = result.ResultPoints; - if (resultPoints == null || resultPoints.Length == 0) - { - return; - } - int width = image.Width; - int height = image.Height; - float minX = width; - float minY = height; - float maxX = 0.0f; - float maxY = 0.0f; - for (int i = 0; i < resultPoints.Length; i++) - { - ResultPoint point = resultPoints[i]; - if (point == null) - { - continue; - } - float x = point.X; - float y = point.Y; - if (x < minX) - { - minX = x; - } - if (y < minY) - { - minY = y; - } - if (x > maxX) - { - maxX = x; - } - if (y > maxY) - { - maxY = y; - } - } - - // Decode left of barcode - if (minX > MIN_DIMENSION_TO_RECUR) - { - doDecodeMultiple(image.crop(0, 0, (int)minX, height), hints, results, xOffset, yOffset, currentDepth + 1); - } - // Decode above barcode - if (minY > MIN_DIMENSION_TO_RECUR) - { - doDecodeMultiple(image.crop(0, 0, width, (int)minY), hints, results, xOffset, yOffset, currentDepth + 1); - } - // Decode right of barcode - if (maxX < width - MIN_DIMENSION_TO_RECUR) - { - doDecodeMultiple(image.crop((int)maxX, 0, width - (int)maxX, height), hints, results, xOffset + (int)maxX, yOffset, currentDepth + 1); - } - // Decode below barcode - if (maxY < height - MIN_DIMENSION_TO_RECUR) - { - doDecodeMultiple(image.crop(0, (int)maxY, width, height - (int)maxY), hints, results, xOffset, yOffset + (int)maxY, currentDepth + 1); - } - } - - private static Result translateResultPoints(Result result, int xOffset, int yOffset) - { - var oldResultPoints = result.ResultPoints; - var newResultPoints = new ResultPoint[oldResultPoints.Length]; - for (int i = 0; i < oldResultPoints.Length; i++) - { - var oldPoint = oldResultPoints[i]; - if (oldPoint != null) - { - newResultPoints[i] = new ResultPoint(oldPoint.X + xOffset, oldPoint.Y + yOffset); - } - } - var newResult = new Result(result.Text, result.RawBytes, newResultPoints, result.BarcodeFormat); - newResult.putAllMetadata(result.ResultMetadata); - return newResult; - } - - /// - /// Locates and decodes a barcode in some format within an image. - /// - /// image of barcode to decode - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image) - { - return _delegate.decode(image); - } - - /// - /// Locates and decodes a barcode in some format within an image. This method also accepts - /// hints, each possibly associated to some data, which may help the implementation decode. - /// - /// image of barcode to decode - /// passed as a from - /// to arbitrary data. The - /// meaning of the data depends upon the hint type. The implementation may or may not do - /// anything with these hints. - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image, IDictionary hints) - { - return _delegate.decode(image, hints); - } - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - public void reset() - { - _delegate.reset(); - } - } -} diff --git a/zxing.core/xx/multi/MultipleBarcodeReader.cs b/zxing.core/xx/multi/MultipleBarcodeReader.cs deleted file mode 100644 index 65fac63..0000000 --- a/zxing.core/xx/multi/MultipleBarcodeReader.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright 2009 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Collections.Generic; - -namespace ZXing.Multi -{ - /// - /// Implementation of this interface attempt to read several barcodes from one image. - /// Sean Owen - /// - /// - public interface MultipleBarcodeReader - { - /// - /// Decodes the multiple. - /// - /// The image. - /// - Result[] decodeMultiple(BinaryBitmap image); - - /// - /// Decodes the multiple. - /// - /// The image. - /// The hints. - /// - Result[] decodeMultiple(BinaryBitmap image, IDictionary hints); - } -} \ No newline at end of file diff --git a/zxing.core/xx/multi/qrcode/QRCodeMultiReader.cs b/zxing.core/xx/multi/qrcode/QRCodeMultiReader.cs deleted file mode 100644 index 92f53b7..0000000 --- a/zxing.core/xx/multi/qrcode/QRCodeMultiReader.cs +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Multi.QrCode.Internal; -using ZXing.QrCode; -using ZXing.QrCode.Internal; - -namespace ZXing.Multi.QrCode -{ - /// - /// This implementation can detect and decode multiple QR Codes in an image. - /// - public sealed class QRCodeMultiReader : QRCodeReader, MultipleBarcodeReader - { - private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0]; - - /// - /// Decodes the multiple. - /// - /// The image. - /// - public Result[] decodeMultiple(BinaryBitmap image) - { - return decodeMultiple(image, null); - } - - /// - /// Decodes the multiple. - /// - /// The image. - /// The hints. - /// - public Result[] decodeMultiple(BinaryBitmap image, IDictionary hints) - { - var results = new List(); - var detectorResults = new MultiDetector(image.BlackMatrix).detectMulti(hints); - foreach (DetectorResult detectorResult in detectorResults) - { - var decoderResult = getDecoder().decode(detectorResult.Bits, hints); - if (decoderResult == null) - continue; - - var points = detectorResult.Points; - // If the code was mirrored: swap the bottom-left and the top-right points. - var data = decoderResult.Other as QRCodeDecoderMetaData; - if (data != null) - { - data.applyMirroredCorrection(points); - } - var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE); - var byteSegments = decoderResult.ByteSegments; - if (byteSegments != null) - { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - var ecLevel = decoderResult.ECLevel; - if (ecLevel != null) - { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - if (decoderResult.StructuredAppend) - { - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, decoderResult.StructuredAppendSequenceNumber); - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, decoderResult.StructuredAppendParity); - } - results.Add(result); - } - if (results.Count == 0) - { - return null; - } - results = ProcessStructuredAppend(results); - return results.ToArray(); - } - - private List ProcessStructuredAppend(List results) - { - bool hasSA = false; - // first, check, if there is at least on SA result in the list - foreach (var result in results) - { - if (result.ResultMetadata.ContainsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) - { - hasSA = true; - break; - } - } - if (!hasSA) - { - return results; - } - // it is, second, split the lists and built a new result list - var newResults = new List(); - var saResults = new List(); - foreach (var result in results) - { - newResults.Add(result); - if (result.ResultMetadata.ContainsKey(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE)) - { - saResults.Add(result); - } - } - // sort and concatenate the SA list items - saResults.Sort(SaSequenceSort); - var concatedText = String.Empty; - var rawBytesLen = 0; - int byteSegmentLength = 0; - foreach (var saResult in saResults) - { - concatedText += saResult.Text; - rawBytesLen += saResult.RawBytes.Length; - if (saResult.ResultMetadata.ContainsKey(ResultMetadataType.BYTE_SEGMENTS)) - { - foreach (var segment in (IEnumerable) saResult.ResultMetadata[ResultMetadataType.BYTE_SEGMENTS]) - { - byteSegmentLength += segment.Length; - } - } - } - var newRawBytes = new byte[rawBytesLen]; - byte[] newByteSegment = new byte[byteSegmentLength]; - int newRawBytesIndex = 0; - int byteSegmentIndex = 0; - foreach (var saResult in saResults) - { - Array.Copy(saResult.RawBytes, 0, newRawBytes, newRawBytesIndex, saResult.RawBytes.Length); - newRawBytesIndex += saResult.RawBytes.Length; - if (saResult.ResultMetadata.ContainsKey(ResultMetadataType.BYTE_SEGMENTS)) - { - foreach (var segment in (IEnumerable) saResult.ResultMetadata[ResultMetadataType.BYTE_SEGMENTS]) - { - Array.Copy(segment, 0, newByteSegment, byteSegmentIndex, segment.Length); - byteSegmentIndex += segment.Length; - } - } - } - Result newResult = new Result(concatedText, newRawBytes, NO_POINTS, BarcodeFormat.QR_CODE); - if (byteSegmentLength > 0) - { - var byteSegmentList = new List(); - byteSegmentList.Add(newByteSegment); - newResult.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegmentList); - } - newResults.Add(newResult); - return newResults; - } - - private int SaSequenceSort(Result a, Result b) - { - var aNumber = (int)(a.ResultMetadata[ResultMetadataType.STRUCTURED_APPEND_SEQUENCE]); - var bNumber = (int)(b.ResultMetadata[ResultMetadataType.STRUCTURED_APPEND_SEQUENCE]); - return aNumber - bNumber; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/multi/qrcode/detector/MultiDetector.cs b/zxing.core/xx/multi/qrcode/detector/MultiDetector.cs deleted file mode 100644 index 7c8142d..0000000 --- a/zxing.core/xx/multi/qrcode/detector/MultiDetector.cs +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; -using ZXing.Common; -using ZXing.QrCode.Internal; - -namespace ZXing.Multi.QrCode.Internal -{ - /// - ///

Encapsulates logic that can detect one or more QR Codes in an image, even if the QR Code - /// is rotated or skewed, or partially obscured.

- /// - /// Sean Owen - /// Hannes Erven - ///
- public sealed class MultiDetector : Detector - { - private static readonly DetectorResult[] EMPTY_DETECTOR_RESULTS = new DetectorResult[0]; - - /// - /// Initializes a new instance of the class. - /// - /// The image. - public MultiDetector(BitMatrix image) - : base(image) - { - } - - /// - /// Detects the multi. - /// - /// The hints. - /// - public DetectorResult[] detectMulti(IDictionary hints) - { - var image = Image; - var resultPointCallback = - hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - var finder = new MultiFinderPatternFinder(image, resultPointCallback); - var infos = finder.findMulti(hints); - - if (infos.Length == 0) - { - return EMPTY_DETECTOR_RESULTS; - } - - var result = new List(); - foreach (FinderPatternInfo info in infos) - { - var oneResult = processFinderPatternInfo(info); - if (oneResult != null) - result.Add(oneResult); - } - if (result.Count == 0) - { - return EMPTY_DETECTOR_RESULTS; - } - else - { - return result.ToArray(); - } - } - } -} diff --git a/zxing.core/xx/multi/qrcode/detector/MultiFinderPatternFinder.cs b/zxing.core/xx/multi/qrcode/detector/MultiFinderPatternFinder.cs deleted file mode 100644 index 542d0ec..0000000 --- a/zxing.core/xx/multi/qrcode/detector/MultiFinderPatternFinder.cs +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; -using ZXing.QrCode.Internal; - -namespace ZXing.Multi.QrCode.Internal -{ - /// - ///

This class attempts to find finder patterns in a QR Code. Finder patterns are the square - /// markers at three corners of a QR Code.

- /// - ///

This class is thread-safe but not reentrant. Each thread must allocate its own object. - /// - ///

In contrast to , this class will return an array of all possible - /// QR code locations in the image.

- /// - ///

Use the TRY_HARDER hint to ask for a more thorough detection.

- /// - /// Sean Owen - /// Hannes Erven - ///
- sealed class MultiFinderPatternFinder : FinderPatternFinder - { - - private static FinderPatternInfo[] EMPTY_RESULT_ARRAY = new FinderPatternInfo[0]; - - // TODO MIN_MODULE_COUNT and MAX_MODULE_COUNT would be great hints to ask the user for - // since it limits the number of regions to decode - - // max. legal count of modules per QR code edge (177) - private static float MAX_MODULE_COUNT_PER_EDGE = 180; - // min. legal count per modules per QR code edge (11) - private static float MIN_MODULE_COUNT_PER_EDGE = 9; - - /// - /// More or less arbitrary cutoff point for determining if two finder patterns might belong - /// to the same code if they differ less than DIFF_MODSIZE_CUTOFF_PERCENT percent in their - /// estimated modules sizes. - /// - private static float DIFF_MODSIZE_CUTOFF_PERCENT = 0.05f; - - /// - /// More or less arbitrary cutoff point for determining if two finder patterns might belong - /// to the same code if they differ less than DIFF_MODSIZE_CUTOFF pixels/module in their - /// estimated modules sizes. - /// - private const float DIFF_MODSIZE_CUTOFF = 0.5f; - - - /// - /// A comparator that orders FinderPatterns by their estimated module size. - /// - private sealed class ModuleSizeComparator : IComparer - { - public int Compare(FinderPattern center1, FinderPattern center2) - { - float value = center2.EstimatedModuleSize - center1.EstimatedModuleSize; - return value < 0.0 ? -1 : value > 0.0 ? 1 : 0; - } - } - - /// - ///

Creates a finder that will search the image for three finder patterns.

- /// - /// image to search - ///
- internal MultiFinderPatternFinder(BitMatrix image) - : base(image) - { - } - - internal MultiFinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) - : base(image, resultPointCallback) - { - } - - /// - /// - /// the 3 best s from our list of candidates. The "best" are - /// those that have been detected at least CENTER_QUORUM times, and whose module - /// size differs from the average among those patterns the least - /// - private FinderPattern[][] selectMutipleBestPatterns() - { - List possibleCenters = PossibleCenters; - int size = possibleCenters.Count; - - if (size < 3) - { - // Couldn't find enough finder patterns - return null; - } - - /* - * Begin HE modifications to safely detect multiple codes of equal size - */ - if (size == 3) - { - return new FinderPattern[][] - { - new FinderPattern[] - { - possibleCenters[0], - possibleCenters[1], - possibleCenters[2] - } - }; - } - - // Sort by estimated module size to speed up the upcoming checks - possibleCenters.Sort(new ModuleSizeComparator()); - - /* - * Now lets start: build a list of tuples of three finder locations that - * - feature similar module sizes - * - are placed in a distance so the estimated module count is within the QR specification - * - have similar distance between upper left/right and left top/bottom finder patterns - * - form a triangle with 90° angle (checked by comparing top right/bottom left distance - * with pythagoras) - * - * Note: we allow each point to be used for more than one code region: this might seem - * counterintuitive at first, but the performance penalty is not that big. At this point, - * we cannot make a good quality decision whether the three finders actually represent - * a QR code, or are just by chance layouted so it looks like there might be a QR code there. - * So, if the layout seems right, lets have the decoder try to decode. - */ - - List results = new List(); // holder for the results - - for (int i1 = 0; i1 < (size - 2); i1++) - { - FinderPattern p1 = possibleCenters[i1]; - if (p1 == null) - { - continue; - } - - for (int i2 = i1 + 1; i2 < (size - 1); i2++) - { - FinderPattern p2 = possibleCenters[i2]; - if (p2 == null) - { - continue; - } - - // Compare the expected module sizes; if they are really off, skip - float vModSize12 = (p1.EstimatedModuleSize - p2.EstimatedModuleSize) / - Math.Min(p1.EstimatedModuleSize, p2.EstimatedModuleSize); - float vModSize12A = Math.Abs(p1.EstimatedModuleSize - p2.EstimatedModuleSize); - if (vModSize12A > DIFF_MODSIZE_CUTOFF && vModSize12 >= DIFF_MODSIZE_CUTOFF_PERCENT) - { - // break, since elements are ordered by the module size deviation there cannot be - // any more interesting elements for the given p1. - break; - } - - for (int i3 = i2 + 1; i3 < size; i3++) - { - FinderPattern p3 = possibleCenters[i3]; - if (p3 == null) - { - continue; - } - - // Compare the expected module sizes; if they are really off, skip - float vModSize23 = (p2.EstimatedModuleSize - p3.EstimatedModuleSize) / - Math.Min(p2.EstimatedModuleSize, p3.EstimatedModuleSize); - float vModSize23A = Math.Abs(p2.EstimatedModuleSize - p3.EstimatedModuleSize); - if (vModSize23A > DIFF_MODSIZE_CUTOFF && vModSize23 >= DIFF_MODSIZE_CUTOFF_PERCENT) - { - // break, since elements are ordered by the module size deviation there cannot be - // any more interesting elements for the given p1. - break; - } - - FinderPattern[] test = { p1, p2, p3 }; - ResultPoint.orderBestPatterns(test); - - // Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal - FinderPatternInfo info = new FinderPatternInfo(test); - float dA = ResultPoint.distance(info.TopLeft, info.BottomLeft); - float dC = ResultPoint.distance(info.TopRight, info.BottomLeft); - float dB = ResultPoint.distance(info.TopLeft, info.TopRight); - - // Check the sizes - float estimatedModuleCount = (dA + dB) / (p1.EstimatedModuleSize * 2.0f); - if (estimatedModuleCount > MAX_MODULE_COUNT_PER_EDGE || - estimatedModuleCount < MIN_MODULE_COUNT_PER_EDGE) - { - continue; - } - - // Calculate the difference of the edge lengths in percent - float vABBC = Math.Abs((dA - dB) / Math.Min(dA, dB)); - if (vABBC >= 0.1f) - { - continue; - } - - // Calculate the diagonal length by assuming a 90° angle at topleft - float dCpy = (float)Math.Sqrt(dA * dA + dB * dB); - // Compare to the real distance in % - float vPyC = Math.Abs((dC - dCpy) / Math.Min(dC, dCpy)); - - if (vPyC >= 0.1f) - { - continue; - } - - // All tests passed! - results.Add(test); - } // end iterate p3 - } // end iterate p2 - } // end iterate p1 - - if (results.Count != 0) - { - return results.ToArray(); - } - - // Nothing found! - return null; - } - - public FinderPatternInfo[] findMulti(IDictionary hints) - { - bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER); - bool pureBarcode = hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE); - BitMatrix image = Image; - int maxI = image.Height; - int maxJ = image.Width; - // We are looking for black/white/black/white/black modules in - // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far - - // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the - // image, and then account for the center being 3 modules in size. This gives the smallest - // number of pixels the center could be, so skip this often. When trying harder, look for all - // QR versions regardless of how dense they are. - int iSkip = (int)(maxI / (MAX_MODULES * 4.0f) * 3); - if (iSkip < MIN_SKIP || tryHarder) - { - iSkip = MIN_SKIP; - } - - int[] stateCount = new int[5]; - for (int i = iSkip - 1; i < maxI; i += iSkip) - { - // Get a row of black/white values - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - int currentState = 0; - for (int j = 0; j < maxJ; j++) - { - if (image[j, i]) - { - // Black pixel - if ((currentState & 1) == 1) - { // Counting white pixels - currentState++; - } - stateCount[currentState]++; - } - else - { // White pixel - if ((currentState & 1) == 0) - { // Counting black pixels - if (currentState == 4) - { // A winner? - if (foundPatternCross(stateCount) && handlePossibleCenter(stateCount, i, j, pureBarcode)) - { // Yes - // Clear state to start looking again - currentState = 0; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - } - else - { // No, shift counts back by two - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - } - } - else - { - stateCount[++currentState]++; - } - } - else - { // Counting white pixels - stateCount[currentState]++; - } - } - } // for j=... - - if (foundPatternCross(stateCount)) - { - handlePossibleCenter(stateCount, i, maxJ, pureBarcode); - } // end if foundPatternCross - } // for i=iSkip-1 ... - FinderPattern[][] patternInfo = selectMutipleBestPatterns(); - if (patternInfo == null) - return EMPTY_RESULT_ARRAY; - List result = new List(); - foreach (FinderPattern[] pattern in patternInfo) - { - ResultPoint.orderBestPatterns(pattern); - result.Add(new FinderPatternInfo(pattern)); - } - - if (result.Count == 0) - { - return EMPTY_RESULT_ARRAY; - } - else - { - return result.ToArray(); - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/CodaBarReader.cs b/zxing.core/xx/oned/CodaBarReader.cs deleted file mode 100644 index a0b5db5..0000000 --- a/zxing.core/xx/oned/CodaBarReader.cs +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Decodes Codabar barcodes.

- /// - /// Bas Vijfwinkel - ///
- public sealed class CodaBarReader : OneDReader - { - // These values are critical for determining how permissive the decoding - // will be. All stripe sizes must be within the window these define, as - // compared to the average stripe size. - private static readonly int MAX_ACCEPTABLE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 2.0f); - private static readonly int PADDING = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 1.5f); - - private const String ALPHABET_STRING = "0123456789-$:/.+ABCD"; - internal static readonly char[] ALPHABET = ALPHABET_STRING.ToCharArray(); - - /** - * These represent the encodings of characters, as patterns of wide and narrow bars. The 7 least-significant bits of - * each int correspond to the pattern of wide and narrow, with 1s representing "wide" and 0s representing narrow. - */ - - internal static int[] CHARACTER_ENCODINGS = { - 0x003, 0x006, 0x009, 0x060, 0x012, 0x042, 0x021, 0x024, 0x030, 0x048, // 0-9 - 0x00c, 0x018, 0x045, 0x051, 0x054, 0x015, 0x01A, 0x029, 0x00B, 0x00E, // -$:/.+ABCD - }; - - // minimal number of characters that should be present (inclusing start and stop characters) - // under normal circumstances this should be set to 3, but can be set higher - // as a last-ditch attempt to reduce false positives. - private const int MIN_CHARACTER_LENGTH = 3; - - // official start and end patterns - private static readonly char[] STARTEND_ENCODING = { 'A', 'B', 'C', 'D' }; - // some codabar generator allow the codabar string to be closed by every - // character. This will cause lots of false positives! - - // some industries use a checksum standard but this is not part of the original codabar standard - // for more information see : http://www.mecsw.com/specs/codabar.html - - // Keep some instance variables to avoid reallocations - private readonly StringBuilder decodeRowResult; - private int[] counters; - private int counterLength; - - public CodaBarReader() - { - decodeRowResult = new StringBuilder(20); - counters = new int[80]; - counterLength = 0; - } - - public override Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - for (var index = 0; index < counters.Length; index++) - counters[index] = 0; - - if (!setCounters(row)) - return null; - - int startOffset = findStartPattern(); - if (startOffset < 0) - return null; - - int nextStart = startOffset; - - decodeRowResult.Length = 0; - do - { - int charOffset = toNarrowWidePattern(nextStart); - if (charOffset == -1) - { - return null; - } - // Hack: We store the position in the alphabet table into a - // StringBuilder, so that we can access the decoded patterns in - // validatePattern. We'll translate to the actual characters later. - decodeRowResult.Append((char) charOffset); - nextStart += 8; - // Stop as soon as we see the end character. - if (decodeRowResult.Length > 1 && - arrayContains(STARTEND_ENCODING, ALPHABET[charOffset])) - { - break; - } - } while (nextStart < counterLength); // no fixed end pattern so keep on reading while data is available - - // Look for whitespace after pattern: - int trailingWhitespace = counters[nextStart - 1]; - int lastPatternSize = 0; - for (int i = -8; i < -1; i++) - { - lastPatternSize += counters[nextStart + i]; - } - - // We need to see whitespace equal to 50% of the last pattern size, - // otherwise this is probably a false positive. The exception is if we are - // at the end of the row. (I.e. the barcode barely fits.) - if (nextStart < counterLength && trailingWhitespace < lastPatternSize/2) - { - return null; - } - - if (!validatePattern(startOffset)) - return null; - - // Translate character table offsets to actual characters. - for (int i = 0; i < decodeRowResult.Length; i++) - { - decodeRowResult[i] = ALPHABET[decodeRowResult[i]]; - } - // Ensure a valid start and end character - char startchar = decodeRowResult[0]; - if (!arrayContains(STARTEND_ENCODING, startchar)) - { - return null; - } - char endchar = decodeRowResult[decodeRowResult.Length - 1]; - if (!arrayContains(STARTEND_ENCODING, endchar)) - { - return null; - } - - // remove stop/start characters character and check if a long enough string is contained - if (decodeRowResult.Length <= MIN_CHARACTER_LENGTH) - { - // Almost surely a false positive ( start + stop + at least 1 character) - return null; - } - - if (!SupportClass.GetValue(hints, DecodeHintType.RETURN_CODABAR_START_END, false)) - { - decodeRowResult.Remove(decodeRowResult.Length - 1, 1); - decodeRowResult.Remove(0, 1); - } - - int runningCount = 0; - for (int i = 0; i < startOffset; i++) - { - runningCount += counters[i]; - } - float left = runningCount; - for (int i = startOffset; i < nextStart - 1; i++) - { - runningCount += counters[i]; - } - float right = runningCount; - - var resultPointCallback = SupportClass.GetValue(hints, DecodeHintType.NEED_RESULT_POINT_CALLBACK, (ResultPointCallback) null); - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint(left, rowNumber)); - resultPointCallback(new ResultPoint(right, rowNumber)); - } - - return new Result( - decodeRowResult.ToString(), - null, - new[] - { - new ResultPoint(left, rowNumber), - new ResultPoint(right, rowNumber) - }, - BarcodeFormat.CODABAR); - } - - private bool validatePattern(int start) - { - // First, sum up the total size of our four categories of stripe sizes; - int[] sizes = { 0, 0, 0, 0 }; - int[] counts = { 0, 0, 0, 0 }; - int end = decodeRowResult.Length - 1; - - // We break out of this loop in the middle, in order to handle - // inter-character spaces properly. - int pos = start; - for (int i = 0; true; i++) - { - int pattern = CHARACTER_ENCODINGS[decodeRowResult[i]]; - for (int j = 6; j >= 0; j--) - { - // Even j = bars, while odd j = spaces. Categories 2 and 3 are for - // long stripes, while 0 and 1 are for short stripes. - int category = (j & 1) + (pattern & 1) * 2; - sizes[category] += counters[pos + j]; - counts[category]++; - pattern >>= 1; - } - if (i >= end) - { - break; - } - // We ignore the inter-character space - it could be of any size. - pos += 8; - } - - // Calculate our allowable size thresholds using fixed-point math. - int[] maxes = new int[4]; - int[] mins = new int[4]; - // Define the threshold of acceptability to be the midpoint between the - // average small stripe and the average large stripe. No stripe lengths - // should be on the "wrong" side of that line. - for (int i = 0; i < 2; i++) - { - mins[i] = 0; // Accept arbitrarily small "short" stripes. - mins[i + 2] = ((sizes[i] << INTEGER_MATH_SHIFT) / counts[i] + - (sizes[i + 2] << INTEGER_MATH_SHIFT) / counts[i + 2]) >> 1; - maxes[i] = mins[i + 2]; - maxes[i + 2] = (sizes[i + 2] * MAX_ACCEPTABLE + PADDING) / counts[i + 2]; - } - - // Now verify that all of the stripes are within the thresholds. - pos = start; - for (int i = 0; true; i++) - { - int pattern = CHARACTER_ENCODINGS[decodeRowResult[i]]; - for (int j = 6; j >= 0; j--) - { - // Even j = bars, while odd j = spaces. Categories 2 and 3 are for - // long stripes, while 0 and 1 are for short stripes. - int category = (j & 1) + (pattern & 1) * 2; - int size = counters[pos + j] << INTEGER_MATH_SHIFT; - if (size < mins[category] || size > maxes[category]) - { - return false; - } - pattern >>= 1; - } - if (i >= end) - { - break; - } - pos += 8; - } - - return true; - } - - /// - /// Records the size of all runs of white and black pixels, starting with white. - /// This is just like recordPattern, except it records all the counters, and - /// uses our builtin "counters" member for storage. - /// - /// row to count from - private bool setCounters(BitArray row) - { - counterLength = 0; - // Start from the first white bit. - int i = row.getNextUnset(0); - int end = row.Size; - if (i >= end) - { - return false; - } - bool isWhite = true; - int count = 0; - while (i < end) - { - if (row[i] ^ isWhite) - { - // that is, exactly one is true - count++; - } - else - { - counterAppend(count); - count = 1; - isWhite = !isWhite; - } - i++; - } - counterAppend(count); - return true; - } - - private void counterAppend(int e) - { - counters[counterLength] = e; - counterLength++; - if (counterLength >= counters.Length) - { - int[] temp = new int[counterLength * 2]; - Array.Copy(counters, 0, temp, 0, counterLength); - counters = temp; - } - } - - private int findStartPattern() - { - for (int i = 1; i < counterLength; i += 2) - { - int charOffset = toNarrowWidePattern(i); - if (charOffset != -1 && arrayContains(STARTEND_ENCODING, ALPHABET[charOffset])) - { - // Look for whitespace before start pattern, >= 50% of width of start pattern - // We make an exception if the whitespace is the first element. - int patternSize = 0; - for (int j = i; j < i + 7; j++) - { - patternSize += counters[j]; - } - if (i == 1 || counters[i - 1] >= patternSize / 2) - { - return i; - } - } - } - return -1; - } - - internal static bool arrayContains(char[] array, char key) - { - if (array != null) - { - foreach (char c in array) - { - if (c == key) - { - return true; - } - } - } - return false; - } - - // Assumes that counters[position] is a bar. - private int toNarrowWidePattern(int position) - { - int end = position + 7; - if (end >= counterLength) - { - return -1; - } - int[] theCounters = counters; - - int maxBar = 0; - int minBar = Int32.MaxValue; - for (int j = position; j < end; j += 2) - { - int currentCounter = theCounters[j]; - if (currentCounter < minBar) - { - minBar = currentCounter; - } - if (currentCounter > maxBar) - { - maxBar = currentCounter; - } - } - int thresholdBar = (minBar + maxBar) / 2; - - int maxSpace = 0; - int minSpace = Int32.MaxValue; - for (int j = position + 1; j < end; j += 2) - { - int currentCounter = theCounters[j]; - if (currentCounter < minSpace) - { - minSpace = currentCounter; - } - if (currentCounter > maxSpace) - { - maxSpace = currentCounter; - } - } - int thresholdSpace = (minSpace + maxSpace) / 2; - - int bitmask = 1 << 7; - int pattern = 0; - for (int i = 0; i < 7; i++) - { - int threshold = (i & 1) == 0 ? thresholdBar : thresholdSpace; - bitmask >>= 1; - if (theCounters[position + i] > threshold) - { - pattern |= bitmask; - } - } - - for (int i = 0; i < CHARACTER_ENCODINGS.Length; i++) - { - if (CHARACTER_ENCODINGS[i] == pattern) - { - return i; - } - } - return -1; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/CodaBarWriter.cs b/zxing.core/xx/oned/CodaBarWriter.cs deleted file mode 100644 index 1fbe0ed..0000000 --- a/zxing.core/xx/oned/CodaBarWriter.cs +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2011 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.OneD -{ - /// - /// This class renders CodaBar as []. - /// - /// dsbnatut@gmail.com (Kazuki Nishiura) - public sealed class CodaBarWriter : OneDimensionalCodeWriter - { - private static readonly char[] START_END_CHARS = {'A', 'B', 'C', 'D'}; - private static readonly char[] ALT_START_END_CHARS = {'T', 'N', '*', 'E'}; - private static readonly char[] CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED = {'/', ':', '+', '.'}; - private static readonly char DEFAULT_GUARD = START_END_CHARS[0]; - - public override bool[] encode(String contents) - { - if (contents.Length < 2) - { - // Can't have a start/end guard, so tentatively add default guards - contents = DEFAULT_GUARD + contents + DEFAULT_GUARD; - } - else - { - // Verify input and calculate decoded length. - char firstChar = Char.ToUpper(contents[0]); - char lastChar = Char.ToUpper(contents[contents.Length - 1]); - bool startsNormal = CodaBarReader.arrayContains(START_END_CHARS, firstChar); - bool endsNormal = CodaBarReader.arrayContains(START_END_CHARS, lastChar); - bool startsAlt = CodaBarReader.arrayContains(ALT_START_END_CHARS, firstChar); - bool endsAlt = CodaBarReader.arrayContains(ALT_START_END_CHARS, lastChar); - if (startsNormal) - { - if (!endsNormal) - { - throw new ArgumentException("Invalid start/end guards: " + contents); - } - // else already has valid start/end - } - else if (startsAlt) - { - if (!endsAlt) - { - throw new ArgumentException("Invalid start/end guards: " + contents); - } - // else already has valid start/end - } - else - { - // Doesn't start with a guard - if (endsNormal || endsAlt) - { - throw new ArgumentException("Invalid start/end guards: " + contents); - } - // else doesn't end with guard either, so add a default - contents = DEFAULT_GUARD + contents + DEFAULT_GUARD; - } - } - - // The start character and the end character are decoded to 10 length each. - int resultLength = 20; - for (int i = 1; i < contents.Length - 1; i++) - { - if (Char.IsDigit(contents[i]) || contents[i] == '-' || contents[i] == '$') - { - resultLength += 9; - } - else if (CodaBarReader.arrayContains(CHARS_WHICH_ARE_TEN_LENGTH_EACH_AFTER_DECODED, contents[i])) - { - resultLength += 10; - } - else - { - throw new ArgumentException("Cannot encode : '" + contents[i] + '\''); - } - } - // A blank is placed between each character. - resultLength += contents.Length - 1; - - var result = new bool[resultLength]; - int position = 0; - for (int index = 0; index < contents.Length; index++) - { - char c = Char.ToUpper(contents[index]); - if (index == 0 || index == contents.Length - 1) - { - // The start/end chars are not in the CodaBarReader.ALPHABET. - switch (c) - { - case 'T': - c = 'A'; - break; - case 'N': - c = 'B'; - break; - case '*': - c = 'C'; - break; - case 'E': - c = 'D'; - break; - } - } - int code = 0; - for (int i = 0; i < CodaBarReader.ALPHABET.Length; i++) - { - // Found any, because I checked above. - if (c == CodaBarReader.ALPHABET[i]) - { - code = CodaBarReader.CHARACTER_ENCODINGS[i]; - break; - } - } - bool color = true; - int counter = 0; - int bit = 0; - while (bit < 7) - { - // A character consists of 7 digit. - result[position] = color; - position++; - if (((code >> (6 - bit)) & 1) == 0 || counter == 1) - { - color = !color; // Flip the color. - bit++; - counter = 0; - } - else - { - counter++; - } - } - if (index < contents.Length - 1) - { - result[position] = false; - position++; - } - } - return result; - } - } -} diff --git a/zxing.core/xx/oned/Code128EncodingOptions.cs b/zxing.core/xx/oned/Code128EncodingOptions.cs deleted file mode 100644 index a681759..0000000 --- a/zxing.core/xx/oned/Code128EncodingOptions.cs +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// The class holds the available options for the QrCodeWriter - /// - public class Code128EncodingOptions : EncodingOptions - { - /// - /// if true, don't switch to codeset C for numbers - /// - public bool ForceCodesetB - { - get - { - if (Hints.ContainsKey(EncodeHintType.CODE128_FORCE_CODESET_B)) - { - return (bool)Hints[EncodeHintType.CODE128_FORCE_CODESET_B]; - } - return false; - } - set - { - Hints[EncodeHintType.CODE128_FORCE_CODESET_B] = value; - } - } - } -} diff --git a/zxing.core/xx/oned/Code128Reader.cs b/zxing.core/xx/oned/Code128Reader.cs deleted file mode 100644 index 69108f5..0000000 --- a/zxing.core/xx/oned/Code128Reader.cs +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Decodes Code 128 barcodes.

- /// - /// Sean Owen - ///
- public sealed class Code128Reader : OneDReader - { - internal static int[][] CODE_PATTERNS = { - new[] {2, 1, 2, 2, 2, 2}, // 0 - new[] {2, 2, 2, 1, 2, 2}, - new[] {2, 2, 2, 2, 2, 1}, - new[] {1, 2, 1, 2, 2, 3}, - new[] {1, 2, 1, 3, 2, 2}, - new[] {1, 3, 1, 2, 2, 2}, // 5 - new[] {1, 2, 2, 2, 1, 3}, - new[] {1, 2, 2, 3, 1, 2}, - new[] {1, 3, 2, 2, 1, 2}, - new[] {2, 2, 1, 2, 1, 3}, - new[] {2, 2, 1, 3, 1, 2}, // 10 - new[] {2, 3, 1, 2, 1, 2}, - new[] {1, 1, 2, 2, 3, 2}, - new[] {1, 2, 2, 1, 3, 2}, - new[] {1, 2, 2, 2, 3, 1}, - new[] {1, 1, 3, 2, 2, 2}, // 15 - new[] {1, 2, 3, 1, 2, 2}, - new[] {1, 2, 3, 2, 2, 1}, - new[] {2, 2, 3, 2, 1, 1}, - new[] {2, 2, 1, 1, 3, 2}, - new[] {2, 2, 1, 2, 3, 1}, // 20 - new[] {2, 1, 3, 2, 1, 2}, - new[] {2, 2, 3, 1, 1, 2}, - new[] {3, 1, 2, 1, 3, 1}, - new[] {3, 1, 1, 2, 2, 2}, - new[] {3, 2, 1, 1, 2, 2}, // 25 - new[] {3, 2, 1, 2, 2, 1}, - new[] {3, 1, 2, 2, 1, 2}, - new[] {3, 2, 2, 1, 1, 2}, - new[] {3, 2, 2, 2, 1, 1}, - new[] {2, 1, 2, 1, 2, 3}, // 30 - new[] {2, 1, 2, 3, 2, 1}, - new[] {2, 3, 2, 1, 2, 1}, - new[] {1, 1, 1, 3, 2, 3}, - new[] {1, 3, 1, 1, 2, 3}, - new[] {1, 3, 1, 3, 2, 1}, // 35 - new[] {1, 1, 2, 3, 1, 3}, - new[] {1, 3, 2, 1, 1, 3}, - new[] {1, 3, 2, 3, 1, 1}, - new[] {2, 1, 1, 3, 1, 3}, - new[] {2, 3, 1, 1, 1, 3}, // 40 - new[] {2, 3, 1, 3, 1, 1}, - new[] {1, 1, 2, 1, 3, 3}, - new[] {1, 1, 2, 3, 3, 1}, - new[] {1, 3, 2, 1, 3, 1}, - new[] {1, 1, 3, 1, 2, 3}, // 45 - new[] {1, 1, 3, 3, 2, 1}, - new[] {1, 3, 3, 1, 2, 1}, - new[] {3, 1, 3, 1, 2, 1}, - new[] {2, 1, 1, 3, 3, 1}, - new[] {2, 3, 1, 1, 3, 1}, // 50 - new[] {2, 1, 3, 1, 1, 3}, - new[] {2, 1, 3, 3, 1, 1}, - new[] {2, 1, 3, 1, 3, 1}, - new[] {3, 1, 1, 1, 2, 3}, - new[] {3, 1, 1, 3, 2, 1}, // 55 - new[] {3, 3, 1, 1, 2, 1}, - new[] {3, 1, 2, 1, 1, 3}, - new[] {3, 1, 2, 3, 1, 1}, - new[] {3, 3, 2, 1, 1, 1}, - new[] {3, 1, 4, 1, 1, 1}, // 60 - new[] {2, 2, 1, 4, 1, 1}, - new[] {4, 3, 1, 1, 1, 1}, - new[] {1, 1, 1, 2, 2, 4}, - new[] {1, 1, 1, 4, 2, 2}, - new[] {1, 2, 1, 1, 2, 4}, // 65 - new[] {1, 2, 1, 4, 2, 1}, - new[] {1, 4, 1, 1, 2, 2}, - new[] {1, 4, 1, 2, 2, 1}, - new[] {1, 1, 2, 2, 1, 4}, - new[] {1, 1, 2, 4, 1, 2}, // 70 - new[] {1, 2, 2, 1, 1, 4}, - new[] {1, 2, 2, 4, 1, 1}, - new[] {1, 4, 2, 1, 1, 2}, - new[] {1, 4, 2, 2, 1, 1}, - new[] {2, 4, 1, 2, 1, 1}, // 75 - new[] {2, 2, 1, 1, 1, 4}, - new[] {4, 1, 3, 1, 1, 1}, - new[] {2, 4, 1, 1, 1, 2}, - new[] {1, 3, 4, 1, 1, 1}, - new[] {1, 1, 1, 2, 4, 2}, // 80 - new[] {1, 2, 1, 1, 4, 2}, - new[] {1, 2, 1, 2, 4, 1}, - new[] {1, 1, 4, 2, 1, 2}, - new[] {1, 2, 4, 1, 1, 2}, - new[] {1, 2, 4, 2, 1, 1}, // 85 - new[] {4, 1, 1, 2, 1, 2}, - new[] {4, 2, 1, 1, 1, 2}, - new[] {4, 2, 1, 2, 1, 1}, - new[] {2, 1, 2, 1, 4, 1}, - new[] {2, 1, 4, 1, 2, 1}, // 90 - new[] {4, 1, 2, 1, 2, 1}, - new[] {1, 1, 1, 1, 4, 3}, - new[] {1, 1, 1, 3, 4, 1}, - new[] {1, 3, 1, 1, 4, 1}, - new[] {1, 1, 4, 1, 1, 3}, // 95 - new[] {1, 1, 4, 3, 1, 1}, - new[] {4, 1, 1, 1, 1, 3}, - new[] {4, 1, 1, 3, 1, 1}, - new[] {1, 1, 3, 1, 4, 1}, - new[] {1, 1, 4, 1, 3, 1}, // 100 - new[] {3, 1, 1, 1, 4, 1}, - new[] {4, 1, 1, 1, 3, 1}, - new[] {2, 1, 1, 4, 1, 2}, - new[] {2, 1, 1, 2, 1, 4}, - new[] {2, 1, 1, 2, 3, 2}, // 105 - new[] {2, 3, 3, 1, 1, 1, 2} - }; - - private static readonly int MAX_AVG_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.25f); - private static readonly int MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f); - - private const int CODE_SHIFT = 98; - - private const int CODE_CODE_C = 99; - private const int CODE_CODE_B = 100; - private const int CODE_CODE_A = 101; - - private const int CODE_FNC_1 = 102; - private const int CODE_FNC_2 = 97; - private const int CODE_FNC_3 = 96; - private const int CODE_FNC_4_A = 101; - private const int CODE_FNC_4_B = 100; - - private const int CODE_START_A = 103; - private const int CODE_START_B = 104; - private const int CODE_START_C = 105; - private const int CODE_STOP = 106; - - private static int[] findStartPattern(BitArray row) - { - int width = row.Size; - int rowOffset = row.getNextSet(0); - - int counterPosition = 0; - int[] counters = new int[6]; - int patternStart = rowOffset; - bool isWhite = false; - int patternLength = counters.Length; - - for (int i = rowOffset; i < width; i++) - { - if (row[i] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - int bestVariance = MAX_AVG_VARIANCE; - int bestMatch = -1; - for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++) - { - int variance = patternMatchVariance(counters, CODE_PATTERNS[startCode], - MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) - { - bestVariance = variance; - bestMatch = startCode; - } - } - if (bestMatch >= 0) - { - // Look for whitespace before start pattern, >= 50% of width of start pattern - if (row.isRange(Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, - false)) - { - return new int[] { patternStart, i, bestMatch }; - } - } - patternStart += counters[0] + counters[1]; - Array.Copy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - private static bool decodeCode(BitArray row, int[] counters, int rowOffset, out int code) - { - code = -1; - if (!recordPattern(row, rowOffset, counters)) - return false; - - int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept - for (int d = 0; d < CODE_PATTERNS.Length; d++) - { - int[] pattern = CODE_PATTERNS[d]; - int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) - { - bestVariance = variance; - code = d; - } - } - // TODO We're overlooking the fact that the STOP pattern has 7 values, not 6. - return code >= 0; - } - - override public Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - bool convertFNC1 = hints != null && hints.ContainsKey(DecodeHintType.ASSUME_GS1); - - int[] startPatternInfo = findStartPattern(row); - if (startPatternInfo == null) - return null; - int startCode = startPatternInfo[2]; - - var rawCodes = new List(20); - rawCodes.Add((byte)startCode); - - int codeSet; - switch (startCode) - { - case CODE_START_A: - codeSet = CODE_CODE_A; - break; - case CODE_START_B: - codeSet = CODE_CODE_B; - break; - case CODE_START_C: - codeSet = CODE_CODE_C; - break; - default: - return null; - } - - bool done = false; - bool isNextShifted = false; - - var result = new StringBuilder(20); - - int lastStart = startPatternInfo[0]; - int nextStart = startPatternInfo[1]; - int[] counters = new int[6]; - - int lastCode = 0; - int code = 0; - int checksumTotal = startCode; - int multiplier = 0; - bool lastCharacterWasPrintable = true; - bool upperMode = false; - bool shiftUpperMode = false; - - while (!done) - { - bool unshift = isNextShifted; - isNextShifted = false; - - // Save off last code - lastCode = code; - - // Decode another code from image - if (!decodeCode(row, counters, nextStart, out code)) - return null; - - rawCodes.Add((byte)code); - - // Remember whether the last code was printable or not (excluding CODE_STOP) - if (code != CODE_STOP) - { - lastCharacterWasPrintable = true; - } - - // Add to checksum computation (if not CODE_STOP of course) - if (code != CODE_STOP) - { - multiplier++; - checksumTotal += multiplier * code; - } - - // Advance to where the next code will to start - lastStart = nextStart; - foreach (int counter in counters) - { - nextStart += counter; - } - - // Take care of illegal start codes - switch (code) - { - case CODE_START_A: - case CODE_START_B: - case CODE_START_C: - return null; - } - - switch (codeSet) - { - - case CODE_CODE_A: - if (code < 64) - { - if (shiftUpperMode == upperMode) - { - result.Append((char) (' ' + code)); - } - else - { - result.Append((char) (' ' + code + 128)); - } - shiftUpperMode = false; - } - else if (code < 96) - { - if (shiftUpperMode == upperMode) - { - result.Append((char) (code - 64)); - } - else - { - result.Append((char) (code + 64)); - } - shiftUpperMode = false; - } - else - { - // Don't let CODE_STOP, which always appears, affect whether whether we think the last - // code was printable or not. - if (code != CODE_STOP) - { - lastCharacterWasPrintable = false; - } - switch (code) - { - case CODE_FNC_1: - if (convertFNC1) - { - if (result.Length == 0) - { - // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code - // is FNC1 then this is GS1-128. We add the symbology identifier. - result.Append("]C1"); - } - else - { - // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS) - result.Append((char) 29); - } - } - break; - case CODE_FNC_2: - case CODE_FNC_3: - // do nothing? - break; - case CODE_FNC_4_A: - if (!upperMode && shiftUpperMode) - { - upperMode = true; - shiftUpperMode = false; - } - else if (upperMode && shiftUpperMode) - { - upperMode = false; - shiftUpperMode = false; - } - else - { - shiftUpperMode = true; - } - break; - case CODE_SHIFT: - isNextShifted = true; - codeSet = CODE_CODE_B; - break; - case CODE_CODE_B: - codeSet = CODE_CODE_B; - break; - case CODE_CODE_C: - codeSet = CODE_CODE_C; - break; - case CODE_STOP: - done = true; - break; - } - } - break; - case CODE_CODE_B: - if (code < 96) - { - if (shiftUpperMode == upperMode) - { - result.Append((char)(' ' + code)); - } - else - { - result.Append((char)(' ' + code + 128)); - } - shiftUpperMode = false; - } - else - { - if (code != CODE_STOP) - { - lastCharacterWasPrintable = false; - } - switch (code) - { - case CODE_FNC_1: - if (convertFNC1) - { - if (result.Length == 0) - { - // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code - // is FNC1 then this is GS1-128. We add the symbology identifier. - result.Append("]C1"); - } - else - { - // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS) - result.Append((char)29); - } - } - break; - case CODE_FNC_2: - case CODE_FNC_3: - // do nothing? - break; - case CODE_FNC_4_B: - if (!upperMode && shiftUpperMode) - { - upperMode = true; - shiftUpperMode = false; - } - else if (upperMode && shiftUpperMode) - { - upperMode = false; - shiftUpperMode = false; - } - else - { - shiftUpperMode = true; - } - break; - case CODE_SHIFT: - isNextShifted = true; - codeSet = CODE_CODE_A; - break; - case CODE_CODE_A: - codeSet = CODE_CODE_A; - break; - case CODE_CODE_C: - codeSet = CODE_CODE_C; - break; - case CODE_STOP: - done = true; - break; - } - } - break; - case CODE_CODE_C: - if (code < 100) - { - if (code < 10) - { - result.Append('0'); - } - result.Append(code); - } - else - { - if (code != CODE_STOP) - { - lastCharacterWasPrintable = false; - } - switch (code) - { - case CODE_FNC_1: - if (convertFNC1) - { - if (result.Length == 0) - { - // GS1 specification 5.4.3.7. and 5.4.6.4. If the first char after the start code - // is FNC1 then this is GS1-128. We add the symbology identifier. - result.Append("]C1"); - } - else - { - // GS1 specification 5.4.7.5. Every subsequent FNC1 is returned as ASCII 29 (GS) - result.Append((char) 29); - } - } - break; - case CODE_CODE_A: - codeSet = CODE_CODE_A; - break; - case CODE_CODE_B: - codeSet = CODE_CODE_B; - break; - case CODE_STOP: - done = true; - break; - } - } - break; - } - - // Unshift back to another code set if we were shifted - if (unshift) - { - codeSet = codeSet == CODE_CODE_A ? CODE_CODE_B : CODE_CODE_A; - } - - } - - int lastPatternSize = nextStart - lastStart; - - // Check for ample whitespace following pattern, but, to do this we first need to remember that - // we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left - // to read off. Would be slightly better to properly read. Here we just skip it: - nextStart = row.getNextUnset(nextStart); - if (!row.isRange(nextStart, - Math.Min(row.Size, nextStart + (nextStart - lastStart) / 2), - false)) - { - return null; - } - - // Pull out from sum the value of the penultimate check code - checksumTotal -= multiplier * lastCode; - // lastCode is the checksum then: - if (checksumTotal % 103 != lastCode) - { - return null; - } - - // Need to pull out the check digits from string - int resultLength = result.Length; - if (resultLength == 0) - { - // false positive - return null; - } - - // Only bother if the result had at least one character, and if the checksum digit happened to - // be a printable character. If it was just interpreted as a control code, nothing to remove. - if (resultLength > 0 && lastCharacterWasPrintable) - { - if (codeSet == CODE_CODE_C) - { - result.Remove(resultLength - 2, 2); - } - else - { - result.Remove(resultLength - 1, 1); - } - } - - float left = (startPatternInfo[1] + startPatternInfo[0]) / 2.0f; - float right = lastStart + lastPatternSize / 2.0f; - - var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) - ? null - : (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint(left, rowNumber)); - resultPointCallback(new ResultPoint(right, rowNumber)); - } - - int rawCodesSize = rawCodes.Count; - var rawBytes = new byte[rawCodesSize]; - for (int i = 0; i < rawCodesSize; i++) - { - rawBytes[i] = rawCodes[i]; - } - - return new Result( - result.ToString(), - rawBytes, - new [] - { - new ResultPoint(left, rowNumber), - new ResultPoint(right, rowNumber) - }, - BarcodeFormat.CODE_128); - } - } -} diff --git a/zxing.core/xx/oned/Code128Writer.cs b/zxing.core/xx/oned/Code128Writer.cs deleted file mode 100644 index 023380d..0000000 --- a/zxing.core/xx/oned/Code128Writer.cs +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders a CODE128 code as a . - /// - /// erik.barbara@gmail.com (Erik Barbara) - /// - public sealed class Code128Writer : OneDimensionalCodeWriter - { - private const int CODE_START_B = 104; - private const int CODE_START_C = 105; - private const int CODE_CODE_B = 100; - private const int CODE_CODE_C = 99; - private const int CODE_STOP = 106; - - // Dummy characters used to specify control characters in input - private const char ESCAPE_FNC_1 = '\u00f1'; - private const char ESCAPE_FNC_2 = '\u00f2'; - private const char ESCAPE_FNC_3 = '\u00f3'; - private const char ESCAPE_FNC_4 = '\u00f4'; - - private const int CODE_FNC_1 = 102; // Code A, Code B, Code C - private const int CODE_FNC_2 = 97; // Code A, Code B - private const int CODE_FNC_3 = 96; // Code A, Code B - private const int CODE_FNC_4_B = 100; // Code B - - private bool forceCodesetB; - - public override BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.CODE_128) - { - throw new ArgumentException("Can only encode CODE_128, but got " + format); - } - - forceCodesetB = (hints != null && - hints.ContainsKey(EncodeHintType.CODE128_FORCE_CODESET_B) && - (bool) hints[EncodeHintType.CODE128_FORCE_CODESET_B]); - - return base.encode(contents, format, width, height, hints); - } - - override public bool[] encode(String contents) - { - int length = contents.Length; - // Check length - if (length < 1 || length > 80) - { - throw new ArgumentException( - "Contents length should be between 1 and 80 characters, but got " + length); - } - // Check content - for (int i = 0; i < length; i++) - { - char c = contents[i]; - if (c < ' ' || c > '~') - { - switch (c) - { - case ESCAPE_FNC_1: - case ESCAPE_FNC_2: - case ESCAPE_FNC_3: - case ESCAPE_FNC_4: - break; - default: - throw new ArgumentException("Bad character in input: " + c); - } - } - } - - var patterns = new List(); // temporary storage for patterns - int checkSum = 0; - int checkWeight = 1; - int codeSet = 0; // selected code (CODE_CODE_B or CODE_CODE_C) - int position = 0; // position in contents - - while (position < length) - { - //Select code to use - int requiredDigitCount = codeSet == CODE_CODE_C ? 2 : 4; - int newCodeSet; - if (isDigits(contents, position, requiredDigitCount)) - { - newCodeSet = forceCodesetB ? CODE_CODE_B : CODE_CODE_C; - } - else - { - newCodeSet = CODE_CODE_B; - } - - //Get the pattern index - int patternIndex; - if (newCodeSet == codeSet) - { - // Encode the current character - // First handle escapes - switch (contents[position]) - { - case ESCAPE_FNC_1: - patternIndex = CODE_FNC_1; - break; - case ESCAPE_FNC_2: - patternIndex = CODE_FNC_2; - break; - case ESCAPE_FNC_3: - patternIndex = CODE_FNC_3; - break; - case ESCAPE_FNC_4: - patternIndex = CODE_FNC_4_B; // FIXME if this ever outputs Code A - break; - default: - // Then handle normal characters otherwise - if (codeSet == CODE_CODE_B) - { - patternIndex = contents[position] - ' '; - } - else - { // CODE_CODE_C - patternIndex = Int32.Parse(contents.Substring(position, 2)); - position++; // Also incremented below - } - break; - } - position++; - } - else - { - // Should we change the current code? - // Do we have a code set? - if (codeSet == 0) - { - // No, we don't have a code set - if (newCodeSet == CODE_CODE_B) - { - patternIndex = CODE_START_B; - } - else - { - // CODE_CODE_C - patternIndex = CODE_START_C; - } - } - else - { - // Yes, we have a code set - patternIndex = newCodeSet; - } - codeSet = newCodeSet; - } - - // Get the pattern - patterns.Add(Code128Reader.CODE_PATTERNS[patternIndex]); - - // Compute checksum - checkSum += patternIndex * checkWeight; - if (position != 0) - { - checkWeight++; - } - } - - // Compute and append checksum - checkSum %= 103; - patterns.Add(Code128Reader.CODE_PATTERNS[checkSum]); - - // Append stop code - patterns.Add(Code128Reader.CODE_PATTERNS[CODE_STOP]); - - // Compute code width - int codeWidth = 0; - foreach (int[] pattern in patterns) - { - foreach (int width in pattern) - { - codeWidth += width; - } - } - - // Compute result - var result = new bool[codeWidth]; - int pos = 0; - foreach (int[] pattern in patterns) - { - pos += appendPattern(result, pos, pattern, true); - } - - return result; - } - - private static bool isDigits(String value, int start, int length) - { - int end = start + length; - int last = value.Length; - for (int i = start; i < end && i < last; i++) - { - char c = value[i]; - if (c < '0' || c > '9') - { - if (c != ESCAPE_FNC_1) - { - return false; - } - end++; // ignore FNC_1 - } - } - return end <= last; // end > last if we've run out of string - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/Code39Reader.cs b/zxing.core/xx/oned/Code39Reader.cs deleted file mode 100644 index 8d18f64..0000000 --- a/zxing.core/xx/oned/Code39Reader.cs +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Decodes Code 39 barcodes. This does not support "Full ASCII Code 39" yet.

- /// Sean Owen - /// @see Code93Reader - ///
- public sealed class Code39Reader : OneDReader - { - internal static String ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"; - private static readonly char[] ALPHABET = ALPHABET_STRING.ToCharArray(); - - /// - /// Returns a string with all possible characters - /// - public static string Alphabet - { - get { return ALPHABET_STRING; } - } - - /// - /// These represent the encodings of characters, as patterns of wide and narrow bars. - /// The 9 least-significant bits of each int correspond to the pattern of wide and narrow, - /// with 1s representing "wide" and 0s representing narrow. - /// - internal static int[] CHARACTER_ENCODINGS = { - 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9 - 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J - 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T - 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, // U-* - 0x0A8, 0x0A2, 0x08A, 0x02A // $-% - }; - - private static readonly int ASTERISK_ENCODING = CHARACTER_ENCODINGS[39]; - - private readonly bool usingCheckDigit; - private readonly bool extendedMode; - private readonly StringBuilder decodeRowResult; - private readonly int[] counters; - - /// - /// Creates a reader that assumes all encoded data is data, and does not treat the final - /// character as a check digit. It will not decoded "extended Code 39" sequences. - /// - public Code39Reader() - :this(false) - { - } - - /// - /// Creates a reader that can be configured to check the last character as a check digit. - /// It will not decoded "extended Code 39" sequences. - /// - /// if true, treat the last data character as a check digit, not - /// data, and verify that the checksum passes. - public Code39Reader(bool usingCheckDigit) - :this(usingCheckDigit, false) - { - } - - /// - /// Creates a reader that can be configured to check the last character as a check digit, - /// or optionally attempt to decode "extended Code 39" sequences that are used to encode - /// the full ASCII character set. - /// - /// if true, treat the last data character as a check digit, not - /// data, and verify that the checksum passes. - /// if true, will attempt to decode extended Code 39 sequences in the text. - public Code39Reader(bool usingCheckDigit, bool extendedMode) - { - this.usingCheckDigit = usingCheckDigit; - this.extendedMode = extendedMode; - decodeRowResult = new StringBuilder(20); - counters = new int[9]; - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// containing encoded string and start/end of barcode - override public Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - for (var index = 0; index < counters.Length; index++) - counters[index] = 0; - decodeRowResult.Length = 0; - - int[] start = findAsteriskPattern(row, counters); - if (start == null) - return null; - - // Read off white space - int nextStart = row.getNextSet(start[1]); - int end = row.Size; - - char decodedChar; - int lastStart; - do - { - if (!recordPattern(row, nextStart, counters)) - return null; - - int pattern = toNarrowWidePattern(counters); - if (pattern < 0) - { - return null; - } - if (!patternToChar(pattern, out decodedChar)) - return null; - decodeRowResult.Append(decodedChar); - lastStart = nextStart; - foreach (int counter in counters) - { - nextStart += counter; - } - // Read off white space - nextStart = row.getNextSet(nextStart); - } while (decodedChar != '*'); - decodeRowResult.Length = decodeRowResult.Length - 1; // remove asterisk - - // Look for whitespace after pattern: - int lastPatternSize = 0; - foreach (int counter in counters) - { - lastPatternSize += counter; - } - int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize; - // If 50% of last pattern size, following last pattern, is not whitespace, fail - // (but if it's whitespace to the very end of the image, that's OK) - if (nextStart != end && (whiteSpaceAfterEnd << 1) < lastPatternSize) - { - return null; - } - - // overriding constructor value is possible - bool useCode39CheckDigit = usingCheckDigit; - if (hints != null && hints.ContainsKey(DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT)) - { - useCode39CheckDigit = (bool) hints[DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT]; - } - - if (useCode39CheckDigit) - { - int max = decodeRowResult.Length - 1; - int total = 0; - for (int i = 0; i < max; i++) - { - total += ALPHABET_STRING.IndexOf(decodeRowResult[i]); - } - if (decodeRowResult[max] != ALPHABET[total % 43]) - { - return null; - } - decodeRowResult.Length = max; - } - - if (decodeRowResult.Length == 0) - { - // false positive - return null; - } - - // overriding constructor value is possible - bool useCode39ExtendedMode = extendedMode; - if (hints != null && hints.ContainsKey(DecodeHintType.USE_CODE_39_EXTENDED_MODE)) - { - useCode39ExtendedMode = (bool)hints[DecodeHintType.USE_CODE_39_EXTENDED_MODE]; - } - - String resultString; - if (useCode39ExtendedMode) - { - resultString = decodeExtended(decodeRowResult.ToString()); - if (resultString == null) - { - if (hints != null && - hints.ContainsKey(DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE) && - Convert.ToBoolean(hints[DecodeHintType.RELAXED_CODE_39_EXTENDED_MODE])) - resultString = decodeRowResult.ToString(); - else - return null; - } - } - else - { - resultString = decodeRowResult.ToString(); - } - - float left = (start[1] + start[0])/2.0f; - float right = lastStart + lastPatternSize / 2.0f; - - var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) - ? null - : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint(left, rowNumber)); - resultPointCallback(new ResultPoint(right, rowNumber)); - } - - return new Result( - resultString, - null, - new[] - { - new ResultPoint(left, rowNumber), - new ResultPoint(right, rowNumber) - }, - BarcodeFormat.CODE_39); - } - - private static int[] findAsteriskPattern(BitArray row, int[] counters) - { - int width = row.Size; - int rowOffset = row.getNextSet(0); - - int counterPosition = 0; - int patternStart = rowOffset; - bool isWhite = false; - int patternLength = counters.Length; - - for (int i = rowOffset; i < width; i++) - { - if (row[i] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - if (toNarrowWidePattern(counters) == ASTERISK_ENCODING) - { - // Look for whitespace before start pattern, >= 50% of width of start pattern - if (row.isRange(Math.Max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false)) - { - return new int[] { patternStart, i }; - } - } - patternStart += counters[0] + counters[1]; - Array.Copy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - // For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions - // per image when using some of our blackbox images. - private static int toNarrowWidePattern(int[] counters) - { - int numCounters = counters.Length; - int maxNarrowCounter = 0; - int wideCounters; - do - { - int minCounter = Int32.MaxValue; - foreach (var counter in counters) - { - if (counter < minCounter && counter > maxNarrowCounter) - { - minCounter = counter; - } - } - maxNarrowCounter = minCounter; - wideCounters = 0; - int totalWideCountersWidth = 0; - int pattern = 0; - for (int i = 0; i < numCounters; i++) - { - int counter = counters[i]; - if (counter > maxNarrowCounter) - { - pattern |= 1 << (numCounters - 1 - i); - wideCounters++; - totalWideCountersWidth += counter; - } - } - if (wideCounters == 3) - { - // Found 3 wide counters, but are they close enough in width? - // We can perform a cheap, conservative check to see if any individual - // counter is more than 1.5 times the average: - for (int i = 0; i < numCounters && wideCounters > 0; i++) - { - int counter = counters[i]; - if (counter > maxNarrowCounter) - { - wideCounters--; - // totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average - if ((counter << 1) >= totalWideCountersWidth) - { - return -1; - } - } - } - return pattern; - } - } while (wideCounters > 3); - return -1; - } - - private static bool patternToChar(int pattern, out char c) - { - for (int i = 0; i < CHARACTER_ENCODINGS.Length; i++) - { - if (CHARACTER_ENCODINGS[i] == pattern) - { - c = ALPHABET[i]; - return true; - } - } - c = '*'; - return false; - } - - private static String decodeExtended(String encoded) - { - int length = encoded.Length; - StringBuilder decoded = new StringBuilder(length); - for (int i = 0; i < length; i++) - { - char c = encoded[i]; - if (c == '+' || c == '$' || c == '%' || c == '/') - { - if (i + 1 >= encoded.Length) - { - return null; - } - - char next = encoded[i + 1]; - char decodedChar = '\0'; - switch (c) - { - case '+': - // +A to +Z map to a to z - if (next >= 'A' && next <= 'Z') - { - decodedChar = (char)(next + 32); - } - else - { - return null; - } - break; - case '$': - // $A to $Z map to control codes SH to SB - if (next >= 'A' && next <= 'Z') - { - decodedChar = (char)(next - 64); - } - else - { - return null; - } - break; - case '%': - // %A to %E map to control codes ESC to US - if (next >= 'A' && next <= 'E') - { - decodedChar = (char)(next - 38); - } - else if (next >= 'F' && next <= 'W') - { - decodedChar = (char)(next - 11); - } - else - { - return null; - } - break; - case '/': - // /A to /O map to ! to , and /Z maps to : - if (next >= 'A' && next <= 'O') - { - decodedChar = (char)(next - 32); - } - else if (next == 'Z') - { - decodedChar = ':'; - } - else - { - return null; - } - break; - } - decoded.Append(decodedChar); - // bump up i again since we read two characters - i++; - } - else - { - decoded.Append(c); - } - } - return decoded.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/Code39Writer.cs b/zxing.core/xx/oned/Code39Writer.cs deleted file mode 100644 index d0ed277..0000000 --- a/zxing.core/xx/oned/Code39Writer.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders a CODE39 code as a . - /// erik.barbara@gmail.com (Erik Barbara) - /// - public sealed class Code39Writer : OneDimensionalCodeWriter - { - /// - /// Encode the contents following specified format. - /// {@code width} and {@code height} are required size. This method may return bigger size - /// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - /// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - /// or {@code height}, {@code IllegalArgumentException} is thrown. - /// - /// - /// - /// - /// - /// - /// - public override BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.CODE_39) - { - throw new ArgumentException("Can only encode CODE_39, but got " + format); - } - return base.encode(contents, format, width, height, hints); - } - - /// - /// Encode the contents to byte array expression of one-dimensional barcode. - /// Start code and end code should be included in result, and side margins should not be included. - /// a {@code boolean[]} of horizontal pixels (false = white, true = black) - /// - /// - /// - public override bool[] encode(String contents) - { - int length = contents.Length; - if (length > 80) - { - throw new ArgumentException( - "Requested contents should be less than 80 digits long, but got " + length); - } - for (int i = 0; i < length; i++) - { - int indexInString = Code39Reader.ALPHABET_STRING.IndexOf(contents[i]); - if (indexInString < 0) - throw new ArgumentException("Requested contents contains a not encodable character: '" + contents[i] + "'"); - } - - int[] widths = new int[9]; - int codeWidth = 24 + 1 + length; - for (int i = 0; i < length; i++) - { - int indexInString = Code39Reader.ALPHABET_STRING.IndexOf(contents[i]); - if (indexInString < 0) - { - throw new ArgumentException("Bad contents: " + contents); - } - toIntArray(Code39Reader.CHARACTER_ENCODINGS[indexInString], widths); - foreach (int width in widths) - { - codeWidth += width; - } - } - var result = new bool[codeWidth]; - toIntArray(Code39Reader.CHARACTER_ENCODINGS[39], widths); - int pos = appendPattern(result, 0, widths, true); - int[] narrowWhite = {1}; - pos += appendPattern(result, pos, narrowWhite, false); - //append next character to byte matrix - for (int i = 0; i < length; i++) - { - int indexInString = Code39Reader.ALPHABET_STRING.IndexOf(contents[i]); - toIntArray(Code39Reader.CHARACTER_ENCODINGS[indexInString], widths); - pos += appendPattern(result, pos, widths, true); - pos += appendPattern(result, pos, narrowWhite, false); - } - toIntArray(Code39Reader.CHARACTER_ENCODINGS[39], widths); - appendPattern(result, pos, widths, true); - return result; - } - - private static void toIntArray(int a, int[] toReturn) - { - for (int i = 0; i < 9; i++) - { - int temp = a & (1 << (8 - i)); - toReturn[i] = temp == 0 ? 1 : 2; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/Code93Reader.cs b/zxing.core/xx/oned/Code93Reader.cs deleted file mode 100644 index d22dd30..0000000 --- a/zxing.core/xx/oned/Code93Reader.cs +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Decodes Code 93 barcodes.

- /// Sean Owen - /// - ///
- public sealed class Code93Reader : OneDReader - { - // Note that 'abcd' are dummy characters in place of control characters. - private const String ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd*"; - private static readonly char[] ALPHABET = ALPHABET_STRING.ToCharArray(); - - /// - /// These represent the encodings of characters, as patterns of wide and narrow bars. - /// The 9 least-significant bits of each int correspond to the pattern of wide and narrow. - /// - private static readonly int[] CHARACTER_ENCODINGS = { - 0x114, 0x148, 0x144, 0x142, 0x128, 0x124, 0x122, 0x150, 0x112, 0x10A, // 0-9 - 0x1A8, 0x1A4, 0x1A2, 0x194, 0x192, 0x18A, 0x168, 0x164, 0x162, 0x134, // A-J - 0x11A, 0x158, 0x14C, 0x146, 0x12C, 0x116, 0x1B4, 0x1B2, 0x1AC, 0x1A6, // K-T - 0x196, 0x19A, 0x16C, 0x166, 0x136, 0x13A, // U-Z - 0x12E, 0x1D4, 0x1D2, 0x1CA, 0x16E, 0x176, 0x1AE, // - - % - 0x126, 0x1DA, 0x1D6, 0x132, 0x15E, // Control chars? $-* - }; - private static readonly int ASTERISK_ENCODING = CHARACTER_ENCODINGS[47]; - - private readonly StringBuilder decodeRowResult; - private readonly int[] counters; - - /// - /// Initializes a new instance of the class. - /// - public Code93Reader() - { - decodeRowResult = new StringBuilder(20); - counters = new int[6]; - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// containing encoded string and start/end of barcode - override public Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - for (var index = 0; index < counters.Length; index++) - counters[index] = 0; - decodeRowResult.Length = 0; - - int[] start = findAsteriskPattern(row); - if (start == null) - return null; - - // Read off white space - int nextStart = row.getNextSet(start[1]); - int end = row.Size; - - char decodedChar; - int lastStart; - do - { - if (!recordPattern(row, nextStart, counters)) - return null; - - int pattern = toPattern(counters); - if (pattern < 0) - { - return null; - } - if (!patternToChar(pattern, out decodedChar)) - return null; - decodeRowResult.Append(decodedChar); - lastStart = nextStart; - foreach (int counter in counters) - { - nextStart += counter; - } - // Read off white space - nextStart = row.getNextSet(nextStart); - } while (decodedChar != '*'); - decodeRowResult.Remove(decodeRowResult.Length - 1, 1); // remove asterisk - - int lastPatternSize = 0; - foreach (int counter in counters) - { - lastPatternSize += counter; - } - - // Should be at least one more black module - if (nextStart == end || !row[nextStart]) - { - return null; - } - - if (decodeRowResult.Length < 2) - { - // false positive -- need at least 2 checksum digits - return null; - } - - if (!checkChecksums(decodeRowResult)) - return null; - // Remove checksum digits - decodeRowResult.Length = decodeRowResult.Length - 2; - - String resultString = decodeExtended(decodeRowResult); - if (resultString == null) - return null; - - float left = (start[1] + start[0])/2.0f; - float right = lastStart + lastPatternSize / 2.0f; - - var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) - ? null - : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint(left, rowNumber)); - resultPointCallback(new ResultPoint(right, rowNumber)); - } - - return new Result( - resultString, - null, - new[] - { - new ResultPoint(left, rowNumber), - new ResultPoint(right, rowNumber) - }, - BarcodeFormat.CODE_93); - } - - private int[] findAsteriskPattern(BitArray row) - { - int width = row.Size; - int rowOffset = row.getNextSet(0); - - for (var index = 0; index < counters.Length; index++) - counters[index] = 0; - int counterPosition = 0; - int patternStart = rowOffset; - bool isWhite = false; - int patternLength = counters.Length; - - for (int i = rowOffset; i < width; i++) - { - if (row[i] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - if (toPattern(counters) == ASTERISK_ENCODING) - { - return new int[] { patternStart, i }; - } - patternStart += counters[0] + counters[1]; - Array.Copy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - private static int toPattern(int[] counters) - { - int max = counters.Length; - int sum = 0; - foreach (var counter in counters) - { - sum += counter; - } - int pattern = 0; - for (int i = 0; i < max; i++) - { - int scaledShifted = (counters[i] << INTEGER_MATH_SHIFT) * 9 / sum; - int scaledUnshifted = scaledShifted >> INTEGER_MATH_SHIFT; - if ((scaledShifted & 0xFF) > 0x7F) - { - scaledUnshifted++; - } - if (scaledUnshifted < 1 || scaledUnshifted > 4) - { - return -1; - } - if ((i & 0x01) == 0) - { - for (int j = 0; j < scaledUnshifted; j++) - { - pattern = (pattern << 1) | 0x01; - } - } - else - { - pattern <<= scaledUnshifted; - } - } - return pattern; - } - - private static bool patternToChar(int pattern, out char c) - { - for (int i = 0; i < CHARACTER_ENCODINGS.Length; i++) - { - if (CHARACTER_ENCODINGS[i] == pattern) - { - c = ALPHABET[i]; - return true; - } - } - c = '*'; - return false; - } - - private static String decodeExtended(StringBuilder encoded) - { - int length = encoded.Length; - StringBuilder decoded = new StringBuilder(length); - for (int i = 0; i < length; i++) - { - char c = encoded[i]; - if (c >= 'a' && c <= 'd') - { - if (i >= length - 1) - { - return null; - } - char next = encoded[i + 1]; - char decodedChar = '\0'; - switch (c) - { - case 'd': - // +A to +Z map to a to z - if (next >= 'A' && next <= 'Z') - { - decodedChar = (char)(next + 32); - } - else - { - return null; - } - break; - case 'a': - // $A to $Z map to control codes SH to SB - if (next >= 'A' && next <= 'Z') - { - decodedChar = (char)(next - 64); - } - else - { - return null; - } - break; - case 'b': - // %A to %E map to control codes ESC to US - if (next >= 'A' && next <= 'E') - { - decodedChar = (char)(next - 38); - } - else if (next >= 'F' && next <= 'W') - { - decodedChar = (char)(next - 11); - } - else - { - return null; - } - break; - case 'c': - // /A to /O map to ! to , and /Z maps to : - if (next >= 'A' && next <= 'O') - { - decodedChar = (char)(next - 32); - } - else if (next == 'Z') - { - decodedChar = ':'; - } - else - { - return null; - } - break; - } - decoded.Append(decodedChar); - // bump up i again since we read two characters - i++; - } - else - { - decoded.Append(c); - } - } - return decoded.ToString(); - } - - private static bool checkChecksums(StringBuilder result) - { - int length = result.Length; - if (!checkOneChecksum(result, length - 2, 20)) - return false; - if (!checkOneChecksum(result, length - 1, 15)) - return false; - return true; - } - - private static bool checkOneChecksum(StringBuilder result, int checkPosition, int weightMax) - { - int weight = 1; - int total = 0; - for (int i = checkPosition - 1; i >= 0; i--) - { - total += weight * ALPHABET_STRING.IndexOf(result[i]); - if (++weight > weightMax) - { - weight = 1; - } - } - if (result[checkPosition] != ALPHABET[total % 47]) - { - return false; - } - return true; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/EAN13Reader.cs b/zxing.core/xx/oned/EAN13Reader.cs deleted file mode 100644 index 7550b9c..0000000 --- a/zxing.core/xx/oned/EAN13Reader.cs +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Implements decoding of the EAN-13 format.

- /// - /// dswitkin@google.com (Daniel Switkin) - /// Sean Owen - /// alasdair@google.com (Alasdair Mackintosh) - ///
- public sealed class EAN13Reader : UPCEANReader - { - // For an EAN-13 barcode, the first digit is represented by the parities used - // to encode the next six digits, according to the table below. For example, - // if the barcode is 5 123456 789012 then the value of the first digit is - // signified by using odd for '1', even for '2', even for '3', odd for '4', - // odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13 - // - // Parity of next 6 digits - // Digit 0 1 2 3 4 5 - // 0 Odd Odd Odd Odd Odd Odd - // 1 Odd Odd Even Odd Even Even - // 2 Odd Odd Even Even Odd Even - // 3 Odd Odd Even Even Even Odd - // 4 Odd Even Odd Odd Even Even - // 5 Odd Even Even Odd Odd Even - // 6 Odd Even Even Even Odd Odd - // 7 Odd Even Odd Even Odd Even - // 8 Odd Even Odd Even Even Odd - // 9 Odd Even Even Odd Even Odd - // - // Note that the encoding for '0' uses the same parity as a UPC barcode. Hence - // a UPC barcode can be converted to an EAN-13 barcode by prepending a 0. - // - // The encoding is represented by the following array, which is a bit pattern - // using Odd = 0 and Even = 1. For example, 5 is represented by: - // - // Odd Even Even Odd Odd Even - // in binary: - // 0 1 1 0 0 1 == 0x19 - // - internal static int[] FIRST_DIGIT_ENCODINGS = { - 0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A - }; - - private readonly int[] decodeMiddleCounters; - - /// - /// Initializes a new instance of the class. - /// - public EAN13Reader() - { - decodeMiddleCounters = new int[4]; - } - - /// - /// Subclasses override this to decode the portion of a barcode between the start - /// and end guard patterns. - /// - /// row of black/white values to search - /// start/end offset of start guard pattern - /// to append decoded chars to - /// - /// horizontal offset of first pixel after the "middle" that was decoded or -1 if decoding could not complete successfully - /// - override protected internal int decodeMiddle(BitArray row, - int[] startRange, - StringBuilder resultString) - { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.Size; - int rowOffset = startRange[1]; - - int lgPatternFound = 0; - - for (int x = 0; x < 6 && rowOffset < end; x++) - { - int bestMatch; - if (!decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS, out bestMatch)) - return -1; - resultString.Append((char) ('0' + bestMatch%10)); - foreach (int counter in counters) - { - rowOffset += counter; - } - if (bestMatch >= 10) - { - lgPatternFound |= 1 << (5 - x); - } - } - - if (!determineFirstDigit(resultString, lgPatternFound)) - return -1; - - int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN); - if (middleRange == null) - return -1; - rowOffset = middleRange[1]; - - for (int x = 0; x < 6 && rowOffset < end; x++) - { - int bestMatch; - if (!decodeDigit(row, counters, rowOffset, L_PATTERNS, out bestMatch)) - return -1; - resultString.Append((char) ('0' + bestMatch)); - foreach (int counter in counters) - { - rowOffset += counter; - } - } - - return rowOffset; - } - - /// - /// Get the format of this decoder. - /// The 1D format. - /// - override internal BarcodeFormat BarcodeFormat - { - get { return BarcodeFormat.EAN_13; } - } - - /// - /// Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded - /// digits in a barcode, determines the implicitly encoded first digit and adds it to the - /// result string. - /// - /// string to insert decoded first digit into - /// int whose bits indicates the pattern of odd/even L/G patterns used to - /// encode digits - /// -1 if first digit cannot be determined - private static bool determineFirstDigit(StringBuilder resultString, int lgPatternFound) - { - for (int d = 0; d < 10; d++) - { - if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d]) - { - resultString.Insert(0, new[] { (char)('0' + d) }); - return true; - } - } - return false; - } - } -} diff --git a/zxing.core/xx/oned/EAN13Writer.cs b/zxing.core/xx/oned/EAN13Writer.cs deleted file mode 100644 index 2036a09..0000000 --- a/zxing.core/xx/oned/EAN13Writer.cs +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders an EAN13 code as a . - /// aripollak@gmail.com (Ari Pollak) - /// - public sealed class EAN13Writer : UPCEANWriter - { - private const int CODE_WIDTH = 3 + // start guard - (7 * 6) + // left bars - 5 + // middle guard - (7 * 6) + // right bars - 3; // end guard - - /// - /// Encode the contents following specified format. - /// {@code width} and {@code height} are required size. This method may return bigger size - /// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - /// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - /// or {@code height}, {@code IllegalArgumentException} is thrown. - /// - /// - /// - /// - /// - /// - /// - public override BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.EAN_13) - { - throw new ArgumentException("Can only encode EAN_13, but got " + format); - } - - return base.encode(contents, format, width, height, hints); - } - - /// - /// Encode the contents to byte array expression of one-dimensional barcode. - /// Start code and end code should be included in result, and side margins should not be included. - /// a {@code boolean[]} of horizontal pixels (false = white, true = black) - /// - /// - /// - override public bool[] encode(String contents) - { - if (contents.Length < 12 || contents.Length > 13) - { - throw new ArgumentException( - "Requested contents should be 12 (without checksum digit) or 13 digits long, but got " + contents.Length); - } - foreach (var ch in contents) - { - if (!Char.IsDigit(ch)) - throw new ArgumentException("Requested contents should only contain digits, but got '" + ch + "'"); - } - - if (contents.Length == 12) - { - contents = CalculateChecksumDigitModulo10(contents); - } - else - { - if (!UPCEANReader.checkStandardUPCEANChecksum(contents)) - { - throw new ArgumentException("Contents do not pass checksum"); - } - } - - int firstDigit = Int32.Parse(contents.Substring(0, 1)); - int parities = EAN13Reader.FIRST_DIGIT_ENCODINGS[firstDigit]; - var result = new bool[CODE_WIDTH]; - int pos = 0; - - pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - // See {@link #EAN13Reader} for a description of how the first digit & left bars are encoded - for (int i = 1; i <= 6; i++) - { - int digit = Int32.Parse(contents.Substring(i, 1)); - if ((parities >> (6 - i) & 1) == 1) - { - digit += 10; - } - pos += appendPattern(result, pos, UPCEANReader.L_AND_G_PATTERNS[digit], false); - } - - pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, false); - - for (int i = 7; i <= 12; i++) - { - int digit = Int32.Parse(contents.Substring(i, 1)); - pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], true); - } - appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - return result; - } - } -} diff --git a/zxing.core/xx/oned/EAN8Reader.cs b/zxing.core/xx/oned/EAN8Reader.cs deleted file mode 100644 index e855ace..0000000 --- a/zxing.core/xx/oned/EAN8Reader.cs +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Implements decoding of the EAN-8 format.

- /// Sean Owen - ///
- public sealed class EAN8Reader : UPCEANReader - { - private readonly int[] decodeMiddleCounters; - - /// - /// Initializes a new instance of the class. - /// - public EAN8Reader() - { - decodeMiddleCounters = new int[4]; - } - - /// - /// Decodes the middle. - /// - /// The row. - /// The start range. - /// The result. - /// - override protected internal int decodeMiddle(BitArray row, - int[] startRange, - StringBuilder result) - { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.Size; - int rowOffset = startRange[1]; - - for (int x = 0; x < 4 && rowOffset < end; x++) - { - int bestMatch; - if (!decodeDigit(row, counters, rowOffset, L_PATTERNS, out bestMatch)) - return -1; - result.Append((char)('0' + bestMatch)); - foreach (int counter in counters) - { - rowOffset += counter; - } - } - - int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN); - if (middleRange == null) - return -1; - rowOffset = middleRange[1]; - - for (int x = 0; x < 4 && rowOffset < end; x++) - { - int bestMatch; - if (!decodeDigit(row, counters, rowOffset, L_PATTERNS, out bestMatch)) - return -1; - result.Append((char)('0' + bestMatch)); - foreach (int counter in counters) - { - rowOffset += counter; - } - } - - return rowOffset; - } - - /// - /// Get the format of this decoder. - /// The 1D format. - /// - override internal BarcodeFormat BarcodeFormat - { - get { return BarcodeFormat.EAN_8; } - } - } -} diff --git a/zxing.core/xx/oned/EAN8Writer.cs b/zxing.core/xx/oned/EAN8Writer.cs deleted file mode 100644 index 0220f2e..0000000 --- a/zxing.core/xx/oned/EAN8Writer.cs +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders an EAN8 code as a . - /// aripollak@gmail.com (Ari Pollak) - /// - public sealed class EAN8Writer : UPCEANWriter - { - private const int CODE_WIDTH = 3 + // start guard - (7 * 4) + // left bars - 5 + // middle guard - (7 * 4) + // right bars - 3; // end guard - - /// - /// Encode the contents following specified format. - /// {@code width} and {@code height} are required size. This method may return bigger size - /// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - /// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - /// or {@code height}, {@code IllegalArgumentException} is thrown. - /// - /// - /// - /// - /// - /// - /// - public override BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.EAN_8) - { - throw new ArgumentException("Can only encode EAN_8, but got " - + format); - } - - return base.encode(contents, format, width, height, hints); - } - - /// - /// - /// - /// a byte array of horizontal pixels (false = white, true = black) - /// - override public bool[] encode(String contents) - { - if (contents.Length < 7 || contents.Length > 8) - { - throw new ArgumentException( - "Requested contents should be 7 (without checksum digit) or 8 digits long, but got " + contents.Length); - } - foreach (var ch in contents) - { - if (!Char.IsDigit(ch)) - throw new ArgumentException("Requested contents should only contain digits, but got '" + ch + "'"); - } - if (contents.Length == 7) - contents = CalculateChecksumDigitModulo10(contents); - - var result = new bool[CODE_WIDTH]; - int pos = 0; - - pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - for (int i = 0; i <= 3; i++) - { - int digit = Int32.Parse(contents.Substring(i, 1)); - pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], false); - } - - pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, false); - - for (int i = 4; i <= 7; i++) - { - int digit = Int32.Parse(contents.Substring(i, 1)); - pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], true); - } - appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true); - - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/EANManufacturerOrgSupport.cs b/zxing.core/xx/oned/EANManufacturerOrgSupport.cs deleted file mode 100644 index adad206..0000000 --- a/zxing.core/xx/oned/EANManufacturerOrgSupport.cs +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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; - -namespace ZXing.OneD -{ - /// - /// Records EAN prefix to GS1 Member Organization, where the member organization - /// correlates strongly with a country. This is an imperfect means of identifying - /// a country of origin by EAN-13 barcode value. See - /// - /// http://en.wikipedia.org/wiki/List_of_GS1_country_codes. - /// - /// Sean Owen - /// - internal sealed class EANManufacturerOrgSupport - { - private List ranges = new List(); - private List countryIdentifiers = new List(); - - internal String lookupCountryIdentifier(String productCode) - { - initIfNeeded(); - int prefix = Int32.Parse(productCode.Substring(0, 3)); - int max = ranges.Count; - for (int i = 0; i < max; i++) - { - int[] range = ranges[i]; - int start = range[0]; - if (prefix < start) - { - return null; - } - int end = range.Length == 1 ? start : range[1]; - if (prefix <= end) - { - return countryIdentifiers[i]; - } - } - return null; - } - - private void add(int[] range, String id) - { - ranges.Add(range); - countryIdentifiers.Add(id); - } - - private void initIfNeeded() - { - if (ranges.Count != 0) - { - return; - } - add(new int[] {0, 19}, "US/CA"); - add(new int[] {30, 39}, "US"); - add(new int[] {60, 139}, "US/CA"); - add(new int[] {300, 379}, "FR"); - add(new int[] {380}, "BG"); - add(new int[] {383}, "SI"); - add(new int[] {385}, "HR"); - add(new int[] {387}, "BA"); - add(new int[] {400, 440}, "DE"); - add(new int[] {450, 459}, "JP"); - add(new int[] {460, 469}, "RU"); - add(new int[] {471}, "TW"); - add(new int[] {474}, "EE"); - add(new int[] {475}, "LV"); - add(new int[] {476}, "AZ"); - add(new int[] {477}, "LT"); - add(new int[] {478}, "UZ"); - add(new int[] {479}, "LK"); - add(new int[] {480}, "PH"); - add(new int[] {481}, "BY"); - add(new int[] {482}, "UA"); - add(new int[] {484}, "MD"); - add(new int[] {485}, "AM"); - add(new int[] {486}, "GE"); - add(new int[] {487}, "KZ"); - add(new int[] {489}, "HK"); - add(new int[] {490, 499}, "JP"); - add(new int[] {500, 509}, "GB"); - add(new int[] {520}, "GR"); - add(new int[] {528}, "LB"); - add(new int[] {529}, "CY"); - add(new int[] {531}, "MK"); - add(new int[] {535}, "MT"); - add(new int[] {539}, "IE"); - add(new int[] {540, 549}, "BE/LU"); - add(new int[] {560}, "PT"); - add(new int[] {569}, "IS"); - add(new int[] {570, 579}, "DK"); - add(new int[] {590}, "PL"); - add(new int[] {594}, "RO"); - add(new int[] {599}, "HU"); - add(new int[] {600, 601}, "ZA"); - add(new int[] {603}, "GH"); - add(new int[] {608}, "BH"); - add(new int[] {609}, "MU"); - add(new int[] {611}, "MA"); - add(new int[] {613}, "DZ"); - add(new int[] {616}, "KE"); - add(new int[] {618}, "CI"); - add(new int[] {619}, "TN"); - add(new int[] {621}, "SY"); - add(new int[] {622}, "EG"); - add(new int[] {624}, "LY"); - add(new int[] {625}, "JO"); - add(new int[] {626}, "IR"); - add(new int[] {627}, "KW"); - add(new int[] {628}, "SA"); - add(new int[] {629}, "AE"); - add(new int[] {640, 649}, "FI"); - add(new int[] {690, 695}, "CN"); - add(new int[] {700, 709}, "NO"); - add(new int[] {729}, "IL"); - add(new int[] {730, 739}, "SE"); - add(new int[] {740}, "GT"); - add(new int[] {741}, "SV"); - add(new int[] {742}, "HN"); - add(new int[] {743}, "NI"); - add(new int[] {744}, "CR"); - add(new int[] {745}, "PA"); - add(new int[] {746}, "DO"); - add(new int[] {750}, "MX"); - add(new int[] {754, 755}, "CA"); - add(new int[] {759}, "VE"); - add(new int[] {760, 769}, "CH"); - add(new int[] {770}, "CO"); - add(new int[] {773}, "UY"); - add(new int[] {775}, "PE"); - add(new int[] {777}, "BO"); - add(new int[] {779}, "AR"); - add(new int[] {780}, "CL"); - add(new int[] {784}, "PY"); - add(new int[] {785}, "PE"); - add(new int[] {786}, "EC"); - add(new int[] {789, 790}, "BR"); - add(new int[] {800, 839}, "IT"); - add(new int[] {840, 849}, "ES"); - add(new int[] {850}, "CU"); - add(new int[] {858}, "SK"); - add(new int[] {859}, "CZ"); - add(new int[] {860}, "YU"); - add(new int[] {865}, "MN"); - add(new int[] {867}, "KP"); - add(new int[] {868, 869}, "TR"); - add(new int[] {870, 879}, "NL"); - add(new int[] {880}, "KR"); - add(new int[] {885}, "TH"); - add(new int[] {888}, "SG"); - add(new int[] {890}, "IN"); - add(new int[] {893}, "VN"); - add(new int[] {896}, "PK"); - add(new int[] {899}, "ID"); - add(new int[] {900, 919}, "AT"); - add(new int[] {930, 939}, "AU"); - add(new int[] {940, 949}, "AZ"); - add(new int[] {955}, "MY"); - add(new int[] {958}, "MO"); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/ITFReader.cs b/zxing.core/xx/oned/ITFReader.cs deleted file mode 100644 index 48115c9..0000000 --- a/zxing.core/xx/oned/ITFReader.cs +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Implements decoding of the ITF format, or Interleaved Two of Five.

- /// - ///

This Reader will scan ITF barcodes of certain lengths only. - /// At the moment it reads length 6, 8, 10, 12, 14, 16, 18, 20, 24, 44 and 48 as these have appeared "in the wild". Not all - /// lengths are scanned, especially shorter ones, to avoid false positives. This in turn is due to a lack of - /// required checksum function.

- /// - ///

The checksum is optional and is not applied by this Reader. The consumer of the decoded - /// value will have to apply a checksum if required.

- /// - ///

http://en.wikipedia.org/wiki/Interleaved_2_of_5 - /// is a great reference for Interleaved 2 of 5 information.

- /// - /// kevin.osullivan@sita.aero, SITA Lab. - ///
- public sealed class ITFReader : OneDReader - { - private static readonly int MAX_AVG_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f); - private static readonly int MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.78f); - - private const int W = 3; // Pixel width of a wide line - private const int N = 1; // Pixed width of a narrow line - - /// - /// Valid ITF lengths. Anything longer than the largest value is also allowed. - /// - private static readonly int[] DEFAULT_ALLOWED_LENGTHS = { 6, 8, 10, 12, 14 }; - private const int LARGEST_DEFAULT_ALLOWED_LENGTH = 14; - - // Stores the actual narrow line width of the image being decoded. - private int narrowLineWidth = -1; - - /// - /// Start/end guard pattern. - /// - /// Note: The end pattern is reversed because the row is reversed before - /// searching for the END_PATTERN - /// - private static readonly int[] START_PATTERN = { N, N, N, N }; - private static readonly int[] END_PATTERN_REVERSED = { N, N, W }; - - /// - /// Patterns of Wide / Narrow lines to indicate each digit - /// - internal static int[][] PATTERNS = new int[][] - { - new int[] {N, N, W, W, N}, // 0 - new int[] {W, N, N, N, W}, // 1 - new int[] {N, W, N, N, W}, // 2 - new int[] {W, W, N, N, N}, // 3 - new int[] {N, N, W, N, W}, // 4 - new int[] {W, N, W, N, N}, // 5 - new int[] {N, W, W, N, N}, // 6 - new int[] {N, N, N, W, W}, // 7 - new int[] {W, N, N, W, N}, // 8 - new int[] {N, W, N, W, N} // 9 - }; - - /// - /// Attempts to decode a one-dimensional barcode format given a single row of - /// an image. - /// - /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// - /// containing encoded string and start/end of barcode - /// - override public Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - // Find out where the Middle section (payload) starts & ends - int[] startRange = decodeStart(row); - if (startRange == null) - return null; - - int[] endRange = decodeEnd(row); - if (endRange == null) - return null; - - StringBuilder result = new StringBuilder(20); - if (!decodeMiddle(row, startRange[1], endRange[0], result)) - return null; - - String resultString = result.ToString(); - - int[] allowedLengths = null; - int maxAllowedLength = LARGEST_DEFAULT_ALLOWED_LENGTH; - if (hints != null && hints.ContainsKey(DecodeHintType.ALLOWED_LENGTHS)) - { - allowedLengths = (int[]) hints[DecodeHintType.ALLOWED_LENGTHS]; - maxAllowedLength = 0; - } - if (allowedLengths == null) - { - allowedLengths = DEFAULT_ALLOWED_LENGTHS; - maxAllowedLength = LARGEST_DEFAULT_ALLOWED_LENGTH; - } - - // To avoid false positives with 2D barcodes (and other patterns), make - // an assumption that the decoded string must be a 'standard' length if it's short - int length = resultString.Length; - bool lengthOK = length > LARGEST_DEFAULT_ALLOWED_LENGTH; - if (!lengthOK) - { - foreach (int allowedLength in allowedLengths) - { - if (length == allowedLength) - { - lengthOK = true; - break; - } - if (allowedLength > maxAllowedLength) - { - maxAllowedLength = allowedLength; - } - } - if (!lengthOK && length > maxAllowedLength) - { - lengthOK = true; - } - if (!lengthOK) - { - return null; - } - } - - var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) - ? null - : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint(startRange[1], rowNumber)); - resultPointCallback(new ResultPoint(endRange[0], rowNumber)); - } - - return new Result( - resultString, - null, // no natural byte representation for these barcodes - new ResultPoint[] - { - new ResultPoint(startRange[1], rowNumber), - new ResultPoint(endRange[0], rowNumber) - }, - BarcodeFormat.ITF); - } - - /// - /// - /// row of black/white values to search - /// offset of start pattern - /// The payload end. - /// to append decoded chars to - /// - /// false, if decoding could not complete successfully - /// - private static bool decodeMiddle(BitArray row, - int payloadStart, - int payloadEnd, - StringBuilder resultString) - { - // Digits are interleaved in pairs - 5 black lines for one digit, and the - // 5 - // interleaved white lines for the second digit. - // Therefore, need to scan 10 lines and then - // split these into two arrays - int[] counterDigitPair = new int[10]; - int[] counterBlack = new int[5]; - int[] counterWhite = new int[5]; - - while (payloadStart < payloadEnd) - { - // Get 10 runs of black/white. - if (!recordPattern(row, payloadStart, counterDigitPair)) - return false; - - // Split them into each array - for (int k = 0; k < 5; k++) - { - int twoK = k << 1; - counterBlack[k] = counterDigitPair[twoK]; - counterWhite[k] = counterDigitPair[twoK + 1]; - } - - int bestMatch; - if (!decodeDigit(counterBlack, out bestMatch)) - return false; - resultString.Append((char)('0' + bestMatch)); - if (!decodeDigit(counterWhite, out bestMatch)) - return false; - resultString.Append((char)('0' + bestMatch)); - - foreach (int counterDigit in counterDigitPair) - { - payloadStart += counterDigit; - } - } - - return true; - } - - /// - /// Identify where the start of the middle / payload section starts. - /// - /// row of black/white values to search - /// Array, containing index of start of 'start block' and end of 'start block' - int[] decodeStart(BitArray row) - { - int endStart = skipWhiteSpace(row); - if (endStart < 0) - return null; - - int[] startPattern = findGuardPattern(row, endStart, START_PATTERN); - if (startPattern == null) - return null; - - // Determine the width of a narrow line in pixels. We can do this by - // getting the width of the start pattern and dividing by 4 because its - // made up of 4 narrow lines. - narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2; - - if (!validateQuietZone(row, startPattern[0])) - return null; - - return startPattern; - } - - /// - /// The start & end patterns must be pre/post fixed by a quiet zone. This - /// zone must be at least 10 times the width of a narrow line. Scan back until - /// we either get to the start of the barcode or match the necessary number of - /// quiet zone pixels. - /// - /// Note: Its assumed the row is reversed when using this method to find - /// quiet zone after the end pattern. - /// - /// ref: http://www.barcode-1.net/i25code.html - /// - /// bit array representing the scanned barcode. - /// index into row of the start or end pattern. - /// false, if the quiet zone cannot be found - private bool validateQuietZone(BitArray row, int startPattern) - { - int quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone - - // if there are not so many pixel at all let's try as many as possible - quietCount = quietCount < startPattern ? quietCount : startPattern; - - for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--) - { - if (row[i]) - { - break; - } - quietCount--; - } - if (quietCount != 0) - { - // Unable to find the necessary number of quiet zone pixels. - return false; - } - return true; - } - - /// - /// Skip all whitespace until we get to the first black line. - /// - /// row of black/white values to search - /// index of the first black line or -1 if no black lines are found in the row. - private static int skipWhiteSpace(BitArray row) - { - int width = row.Size; - int endStart = row.getNextSet(0); - if (endStart == width) - { - return -1; - } - - return endStart; - } - - /// - /// Identify where the end of the middle / payload section ends. - /// - /// row of black/white values to search - /// Array, containing index of start of 'end block' and end of 'end - /// block' or null, if nothing found - int[] decodeEnd(BitArray row) - { - // For convenience, reverse the row and then - // search from 'the start' for the end block - row.reverse(); - int endStart = skipWhiteSpace(row); - if (endStart < 0) - return null; - int[] endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED); - if (endPattern == null) - { - row.reverse(); - return null; - } - - // The start & end patterns must be pre/post fixed by a quiet zone. This - // zone must be at least 10 times the width of a narrow line. - // ref: http://www.barcode-1.net/i25code.html - if (!validateQuietZone(row, endPattern[0])) - { - row.reverse(); - return null; - } - - // Now recalculate the indices of where the 'endblock' starts & stops to - // accommodate - // the reversed nature of the search - int temp = endPattern[0]; - endPattern[0] = row.Size - endPattern[1]; - endPattern[1] = row.Size - temp; - - row.reverse(); - return endPattern; - } - - /// - /// - /// row of black/white values to search - /// position to start search - /// pattern of counts of number of black and white pixels that are being searched for as a pattern - /// start/end horizontal offset of guard pattern, as an array of two ints - private static int[] findGuardPattern(BitArray row, - int rowOffset, - int[] pattern) - { - - // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be - // merged to a single method. - int patternLength = pattern.Length; - int[] counters = new int[patternLength]; - int width = row.Size; - bool isWhite = false; - - int counterPosition = 0; - int patternStart = rowOffset; - for (int x = rowOffset; x < width; x++) - { - if (row[x] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) - { - return new int[] { patternStart, x }; - } - patternStart += counters[0] + counters[1]; - Array.Copy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - /// - /// Attempts to decode a sequence of ITF black/white lines into single - /// digit. - /// - /// the counts of runs of observed black/white/black/... values - /// The decoded digit - /// - /// false, if digit cannot be decoded - /// - private static bool decodeDigit(int[] counters, out int bestMatch) - { - int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept - bestMatch = -1; - int max = PATTERNS.Length; - for (int i = 0; i < max; i++) - { - int[] pattern = PATTERNS[i]; - int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) - { - bestVariance = variance; - bestMatch = i; - } - } - return bestMatch >= 0; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/ITFWriter.cs b/zxing.core/xx/oned/ITFWriter.cs deleted file mode 100644 index f2f816e..0000000 --- a/zxing.core/xx/oned/ITFWriter.cs +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders a ITF code as a . - /// - /// erik.barbara@gmail.com (Erik Barbara) - /// - public sealed class ITFWriter : OneDimensionalCodeWriter - { - private static readonly int[] START_PATTERN = {1, 1, 1, 1}; - private static readonly int[] END_PATTERN = {3, 1, 1}; - - /// - /// Encode the contents following specified format. - /// {@code width} and {@code height} are required size. This method may return bigger size - /// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - /// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - /// or {@code height}, {@code IllegalArgumentException} is thrown. - /// - /// - /// - /// - /// - /// - /// - public override BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.ITF) - { - throw new ArgumentException("Can only encode ITF, but got " + format); - } - - return base.encode(contents, format, width, height, hints); - } - - /// - /// Encode the contents to bool array expression of one-dimensional barcode. - /// Start code and end code should be included in result, and side margins should not be included. - /// a {@code bool[]} of horizontal pixels (false = white, true = black) - /// - /// - /// - override public bool[] encode(String contents) - { - int length = contents.Length; - if (length % 2 != 0) - { - throw new ArgumentException("The lenght of the input should be even"); - } - if (length > 80) - { - throw new ArgumentException( - "Requested contents should be less than 80 digits long, but got " + length); - } - for (var i = 0; i < length; i++) - { - if (!Char.IsDigit(contents[i])) - throw new ArgumentException("Requested contents should only contain digits, but got '" + contents[i] + "'"); - } - - var result = new bool[9 + 9 * length]; - int pos = appendPattern(result, 0, START_PATTERN, true); - for (int i = 0; i < length; i += 2) - { - int one = Convert.ToInt32(contents[i].ToString(), 10); - int two = Convert.ToInt32(contents[i + 1].ToString(), 10); - int[] encoding = new int[18]; - for (int j = 0; j < 5; j++) - { - encoding[j << 1] = ITFReader.PATTERNS[one][j]; - encoding[(j << 1) + 1] = ITFReader.PATTERNS[two][j]; - } - pos += appendPattern(result, pos, encoding, true); - } - appendPattern(result, pos, END_PATTERN, true); - - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/MSIReader.cs b/zxing.core/xx/oned/MSIReader.cs deleted file mode 100644 index 8ce6d8d..0000000 --- a/zxing.core/xx/oned/MSIReader.cs +++ /dev/null @@ -1,356 +0,0 @@ -/* - * 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.Text; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// Decodes MSI barcodes. - /// - public sealed class MSIReader : OneDReader - { - internal static String ALPHABET_STRING = "0123456789"; - private static readonly char[] ALPHABET = ALPHABET_STRING.ToCharArray(); - - /// - /// These represent the encodings of characters, as patterns of wide and narrow bars. - /// The 9 least-significant bits of each int correspond to the pattern of wide and narrow, - /// with 1s representing "wide" and 0s representing narrow. - /// - internal static int[] CHARACTER_ENCODINGS = { - 0x924, 0x926, 0x934, 0x936, 0x9A4, 0x9A6, 0x9B4, 0x9B6, 0xD24, 0xD26 // 0-9 - }; - - private const int START_ENCODING = 0x06; - private const int END_ENCODING = 0x09; - - private readonly bool usingCheckDigit; - private readonly StringBuilder decodeRowResult; - private readonly int[] counters; - private int averageCounterWidth; - - /// - /// Creates a reader that assumes all encoded data is data, and does not treat the final - /// character as a check digit. - /// - public MSIReader() - : this(false) - { - } - - /// - /// Creates a reader that can be configured to check the last character as a check digit, - /// - /// if true, treat the last data character as a check digit, not - /// data, and verify that the checksum passes. - public MSIReader(bool usingCheckDigit) - { - this.usingCheckDigit = usingCheckDigit; - decodeRowResult = new StringBuilder(20); - counters = new int[8]; - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// containing encoded string and start/end of barcode - override public Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - for (var index = 0; index < counters.Length; index++) - counters[index] = 0; - decodeRowResult.Length = 0; - - int[] start = findStartPattern(row, counters); - if (start == null) - return null; - - // Read off white space - int nextStart = row.getNextSet(start[1]); - - char decodedChar; - int lastStart = nextStart; - int pattern; - do - { - if (!recordPattern(row, nextStart, counters, 8)) - { - // not enough bars for a number but perhaps enough for the end pattern - var endPattern = findEndPattern(row, nextStart, counters); - if (endPattern == null) - return null; - lastStart = nextStart; - nextStart = endPattern[1]; - break; - } - pattern = toPattern(counters, 8); - if (!patternToChar(pattern, out decodedChar)) - { - // pattern doesn't result in an encoded number - // but it could be the end pattern followed by some black areas - var endPattern = findEndPattern(row, nextStart, counters); - if (endPattern == null) - return null; - lastStart = nextStart; - nextStart = endPattern[1]; - break; - } - decodeRowResult.Append(decodedChar); - lastStart = nextStart; - foreach (int counter in counters) - { - nextStart += counter; - } - // Read off white space - nextStart = row.getNextSet(nextStart); - } while (decodedChar != '*'); - - // at least 3 digits to prevent false positives within other kind - // of codes like PDF417 - if (decodeRowResult.Length < 3) - { - return null; - } - - var rawBytes = Encoding.UTF8.GetBytes(decodeRowResult.ToString()); - var resultString = decodeRowResult.ToString(); - - if (usingCheckDigit) - { - var resultStringWithoutChecksum = resultString.Substring(0, resultString.Length - 1); - int checkSum = CalculateChecksumLuhn(resultStringWithoutChecksum); - if ((char)(checkSum + 48) != resultString[resultStringWithoutChecksum.Length]) - { - return null; - } - } - - float left = (float)(start[1] + start[0]) / 2.0f; - float right = (float)(nextStart + lastStart) / 2.0f; - - var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) - ? null - : (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint(left, rowNumber)); - resultPointCallback(new ResultPoint(right, rowNumber)); - } - - return new Result( - resultString, - rawBytes, - new[] - { - new ResultPoint(left, rowNumber), - new ResultPoint(right, rowNumber) - }, - BarcodeFormat.MSI); - } - - private int[] findStartPattern(BitArray row, int[] counters) - { - const int patternLength = 2; - - int width = row.Size; - int rowOffset = row.getNextSet(0); - - int counterPosition = 0; - int patternStart = rowOffset; - bool isWhite = false; - - counters[0] = 0; - counters[1] = 0; - for (int i = rowOffset; i < width; i++) - { - if (row[i] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - // narrow and wide areas should be as near as possible to factor 2 - // lets say we will check 1.5 <= factor <= 5 - var factorNarrowToWide = ((float)counters[0]) / ((float)counters[1]); - if (factorNarrowToWide >= 1.5 && factorNarrowToWide <= 5) - { - calculateAverageCounterWidth(counters, patternLength); - if (toPattern(counters, patternLength) == START_ENCODING) - { - // Look for whitespace before start pattern, >= 50% of width of start pattern - if (row.isRange(Math.Max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false)) - { - return new int[] {patternStart, i}; - } - } - } - patternStart += counters[0] + counters[1]; - Array.Copy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - private int[] findEndPattern(BitArray row, int rowOffset, int[] counters) - { - const int patternLength = 3; - - int width = row.Size; - - int counterPosition = 0; - int patternStart = rowOffset; - bool isWhite = false; - - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - for (int i = rowOffset; i < width; i++) - { - if (row[i] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - var factorNarrowToWide = ((float)counters[1]) / ((float)counters[0]); - if (factorNarrowToWide >= 1.5 && factorNarrowToWide <= 5) - { - if (toPattern(counters, patternLength) == END_ENCODING) - { - // Look for whitespace after end pattern, >= 50% of width of end pattern - var minEndOfWhite = Math.Min(row.Size - 1, i + ((i - patternStart) >> 1)); - if (row.isRange(i, minEndOfWhite, false)) - { - return new int[] {patternStart, i}; - } - } - } - return null; - } - counterPosition++; - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - private void calculateAverageCounterWidth(int[] counters, int patternLength) - { - // look for the minimum and the maximum width of the bars - // there are only two sizes for MSI barcodes - // all numbers are encoded as a chain of the pattern 100 and 110 - // the complete pattern of one number always starts with 1 or 11 (black bar(s)) - int minCounter = Int32.MaxValue; - int maxCounter = 0; - for (var index = 0; index < patternLength; index++) - { - var counter = counters[index]; - if (counter < minCounter) - { - minCounter = counter; - } - if (counter > maxCounter) - { - maxCounter = counter; - } - } - // calculate the average of the minimum and maximum width - // using some bit shift to get a higher resolution without floating point arithmetic - averageCounterWidth = ((maxCounter << 8) + (minCounter << 8)) / 2; - } - - private int toPattern(int[] counters, int patternLength) - { - // calculating the encoded value from the pattern - int pattern = 0; - int bit = 1; - int doubleBit = 3; - for (var index = 0; index < patternLength; index++) - { - var counter = counters[index]; - if ((counter << 8) < averageCounterWidth) - { - pattern = (pattern << 1) | bit; - } - else - { - pattern = (pattern << 2) | doubleBit; - } - bit = bit ^ 1; - doubleBit = doubleBit ^ 3; - } - - return pattern; - } - - private static bool patternToChar(int pattern, out char c) - { - for (int i = 0; i < CHARACTER_ENCODINGS.Length; i++) - { - if (CHARACTER_ENCODINGS[i] == pattern) - { - c = ALPHABET[i]; - return true; - } - } - c = '*'; - return false; - } - - private static readonly int[] doubleAndCrossSum = new [] { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 }; - - private static int CalculateChecksumLuhn(string number) - { - var checksum = 0; - - for (var index = number.Length - 2; index >= 0; index -= 2) - { - var digit = number[index] - 48; - checksum += digit; - } - for (var index = number.Length - 1; index >= 0; index -= 2) - { - var digit = doubleAndCrossSum[number[index] - 48]; - checksum += digit; - } - - return (10 - (checksum % 10)) % 10; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/MSIWriter.cs b/zxing.core/xx/oned/MSIWriter.cs deleted file mode 100644 index e90fb38..0000000 --- a/zxing.core/xx/oned/MSIWriter.cs +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2013 ZXing.Net authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders a MSI code as a . - /// - public sealed class MSIWriter : OneDimensionalCodeWriter - { - private static readonly int[] startWidths = new [] { 2, 1 }; - private static readonly int[] endWidths = new[] { 1, 2, 1 }; - private static readonly int[][] numberWidths = new[] - { - new[] { 1, 2, 1, 2, 1, 2, 1, 2 }, - new[] { 1, 2, 1, 2, 1, 2, 2, 1 }, - new[] { 1, 2, 1, 2, 2, 1, 1, 2 }, - new[] { 1, 2, 1, 2, 2, 1, 2, 1 }, - new[] { 1, 2, 2, 1, 1, 2, 1, 2 }, - new[] { 1, 2, 2, 1, 1, 2, 2, 1 }, - new[] { 1, 2, 2, 1, 2, 1, 1, 2 }, - new[] { 1, 2, 2, 1, 2, 1, 2, 1 }, - new[] { 2, 1, 1, 2, 1, 2, 1, 2 }, - new[] { 2, 1, 1, 2, 1, 2, 2, 1 } - }; - - /// - /// Encode the contents following specified format. - /// {@code width} and {@code height} are required size. This method may return bigger size - /// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - /// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - /// or {@code height}, {@code IllegalArgumentException} is thrown. - /// - /// - /// - /// - /// - /// - /// - public override BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.MSI) - { - throw new ArgumentException("Can only encode MSI, but got " + format); - } - return base.encode(contents, format, width, height, hints); - } - - /// - /// Encode the contents to byte array expression of one-dimensional barcode. - /// Start code and end code should be included in result, and side margins should not be included. - /// a {@code boolean[]} of horizontal pixels (false = white, true = black) - /// - /// - /// - override public bool[] encode(String contents) - { - var length = contents.Length; - for (var i = 0; i < length; i++) - { - int indexInString = MSIReader.ALPHABET_STRING.IndexOf(contents[i]); - if (indexInString < 0) - throw new ArgumentException("Requested contents contains a not encodable character: '" + contents[i] + "'"); - } - - var codeWidth = 3 + length*12 + 4; - var result = new bool[codeWidth]; - var pos = appendPattern(result, 0, startWidths, true); - for (var i = 0; i < length; i++) - { - var indexInString = MSIReader.ALPHABET_STRING.IndexOf(contents[i]); - var widths = numberWidths[indexInString]; - pos += appendPattern(result, pos, widths, true); - } - appendPattern(result, pos, endWidths, true); - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/MultiFormatOneDReader.cs b/zxing.core/xx/oned/MultiFormatOneDReader.cs deleted file mode 100644 index 32bc9c0..0000000 --- a/zxing.core/xx/oned/MultiFormatOneDReader.cs +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.OneD.RSS; -using ZXing.OneD.RSS.Expanded; - -namespace ZXing.OneD -{ - /// - /// dswitkin@google.com (Daniel Switkin) - /// Sean Owen - /// - public sealed class MultiFormatOneDReader : OneDReader - { - private readonly IList readers; - - /// - /// Initializes a new instance of the class. - /// - /// The hints. - public MultiFormatOneDReader(IDictionary hints) - { - var possibleFormats = hints == null || !hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS) ? null : - (IList)hints[DecodeHintType.POSSIBLE_FORMATS]; - readers = new List(); - if (possibleFormats != null) - { - if (possibleFormats.Contains(BarcodeFormat.All_1D) || - possibleFormats.Contains(BarcodeFormat.EAN_13) || - possibleFormats.Contains(BarcodeFormat.UPC_A) || - possibleFormats.Contains(BarcodeFormat.EAN_8) || - possibleFormats.Contains(BarcodeFormat.UPC_E)) - { - readers.Add(new MultiFormatUPCEANReader(hints)); - } - if (possibleFormats.Contains(BarcodeFormat.MSI)) - { - // MSI needs to be activated explicit - bool useMsiCheckDigit = (hints.ContainsKey(DecodeHintType.ASSUME_MSI_CHECK_DIGIT) - ? (bool)hints[DecodeHintType.ASSUME_MSI_CHECK_DIGIT] - : false); - readers.Add(new MSIReader(useMsiCheckDigit)); - } - if (possibleFormats.Contains(BarcodeFormat.CODE_39) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - bool useCode39CheckDigit = hints.ContainsKey(DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT) && - (bool) hints[DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT]; - bool useCode39ExtendedMode = hints.ContainsKey(DecodeHintType.USE_CODE_39_EXTENDED_MODE) && - (bool) hints[DecodeHintType.USE_CODE_39_EXTENDED_MODE]; - readers.Add(new Code39Reader(useCode39CheckDigit, useCode39ExtendedMode)); - } - if (possibleFormats.Contains(BarcodeFormat.CODE_93) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new Code93Reader()); - } - if (possibleFormats.Contains(BarcodeFormat.CODE_128) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new Code128Reader()); - } - if (possibleFormats.Contains(BarcodeFormat.ITF) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new ITFReader()); - } - if (possibleFormats.Contains(BarcodeFormat.CODABAR) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new CodaBarReader()); - } - if (possibleFormats.Contains(BarcodeFormat.RSS_14) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new RSS14Reader()); - } - if (possibleFormats.Contains(BarcodeFormat.RSS_EXPANDED) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new RSSExpandedReader()); - } - } - if (readers.Count == 0) - { - bool useCode39CheckDigit = hints != null && hints.ContainsKey(DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT) && - (bool) hints[DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT]; - bool useCode39ExtendedMode = hints != null && hints.ContainsKey(DecodeHintType.USE_CODE_39_EXTENDED_MODE) && - (bool) hints[DecodeHintType.USE_CODE_39_EXTENDED_MODE]; - // MSI needs to be activated explicit - - readers.Add(new MultiFormatUPCEANReader(hints)); - readers.Add(new Code39Reader(useCode39CheckDigit, useCode39ExtendedMode)); - readers.Add(new CodaBarReader()); - readers.Add(new Code93Reader()); - readers.Add(new Code128Reader()); - readers.Add(new ITFReader()); - readers.Add(new RSS14Reader()); - readers.Add(new RSSExpandedReader()); - } - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// - /// containing encoded string and start/end of barcode or null, if an error occurs or barcode cannot be found - /// - override public Result decodeRow(int rowNumber, - BitArray row, - IDictionary hints) - { - foreach (OneDReader reader in readers) - { - var result = reader.decodeRow(rowNumber, row, hints); - if (result != null) - return result; - } - - return null; - } - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - public override void reset() - { - foreach (Reader reader in readers) - { - reader.reset(); - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/MultiFormatUPCEANReader.cs b/zxing.core/xx/oned/MultiFormatUPCEANReader.cs deleted file mode 100644 index 90beae9..0000000 --- a/zxing.core/xx/oned/MultiFormatUPCEANReader.cs +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

A reader that can read all available UPC/EAN formats. If a caller wants to try to - /// read all such formats, it is most efficient to use this implementation rather than invoke - /// individual readers.

- /// Sean Owen - ///
- public sealed class MultiFormatUPCEANReader : OneDReader - { - private readonly UPCEANReader[] readers; - - /// - /// Initializes a new instance of the class. - /// - /// The hints. - public MultiFormatUPCEANReader(IDictionary hints) - { - var possibleFormats = hints == null || !hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS) ? null : - (IList)hints[DecodeHintType.POSSIBLE_FORMATS]; - var readers = new List(); - if (possibleFormats != null) - { - if (possibleFormats.Contains(BarcodeFormat.EAN_13) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new EAN13Reader()); - } - else if (possibleFormats.Contains(BarcodeFormat.UPC_A) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new UPCAReader()); - } - if (possibleFormats.Contains(BarcodeFormat.EAN_8) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new EAN8Reader()); - } - if (possibleFormats.Contains(BarcodeFormat.UPC_E) || possibleFormats.Contains(BarcodeFormat.All_1D)) - { - readers.Add(new UPCEReader()); - } - } - if (readers.Count == 0) - { - readers.Add(new EAN13Reader()); - // UPC-A is covered by EAN-13 - readers.Add(new EAN8Reader()); - readers.Add(new UPCEReader()); - } - this.readers = readers.ToArray(); - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// - /// containing encoded string and start/end of barcode or null if an error occurs or barcode cannot be found - /// - override public Result decodeRow(int rowNumber, - BitArray row, - IDictionary hints) - { - // Compute this location once and reuse it on multiple implementations - int[] startGuardPattern = UPCEANReader.findStartGuardPattern(row); - if (startGuardPattern == null) - return null; - - foreach (UPCEANReader reader in readers) - { - Result result = reader.decodeRow(rowNumber, row, startGuardPattern, hints); - if (result == null) - continue; - - // Special case: a 12-digit code encoded in UPC-A is identical to a "0" - // followed by those 12 digits encoded as EAN-13. Each will recognize such a code, - // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0". - // Individually these are correct and their readers will both read such a code - // and correctly call it EAN-13, or UPC-A, respectively. - // - // In this case, if we've been looking for both types, we'd like to call it - // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read - // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A - // result if appropriate. - // - // But, don't return UPC-A if UPC-A was not a requested format! - bool ean13MayBeUPCA = - result.BarcodeFormat == BarcodeFormat.EAN_13 && - result.Text[0] == '0'; - var possibleFormats = - hints == null || !hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS) ? null : (IList)hints[DecodeHintType.POSSIBLE_FORMATS]; - bool canReturnUPCA = possibleFormats == null || possibleFormats.Contains(BarcodeFormat.UPC_A) || possibleFormats.Contains(BarcodeFormat.All_1D); - - if (ean13MayBeUPCA && canReturnUPCA) - { - // Transfer the metdata across - var resultUPCA = new Result(result.Text.Substring(1), - result.RawBytes, - result.ResultPoints, - BarcodeFormat.UPC_A); - resultUPCA.putAllMetadata(result.ResultMetadata); - return resultUPCA; - } - return result; - } - - return null; - } - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - public override void reset() - { - foreach (Reader reader in readers) - { - reader.reset(); - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/OneDReader.cs b/zxing.core/xx/oned/OneDReader.cs deleted file mode 100644 index 871f056..0000000 --- a/zxing.core/xx/oned/OneDReader.cs +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// Encapsulates functionality and implementation that is common to all families - /// of one-dimensional barcodes. - /// dswitkin@google.com (Daniel Switkin) - /// Sean Owen - /// - public abstract class OneDReader : Reader - { - /// - /// - /// - protected static int INTEGER_MATH_SHIFT = 8; - /// - /// - /// - protected static int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT; - - /// - /// Locates and decodes a barcode in some format within an image. - /// - /// image of barcode to decode - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image) - { - return decode(image, null); - } - - /// - /// Locates and decodes a barcode in some format within an image. This method also accepts - /// hints, each possibly associated to some data, which may help the implementation decode. - /// Note that we don't try rotation without the try harder flag, even if rotation was supported. - /// - /// image of barcode to decode - /// passed as a from - /// to arbitrary data. The - /// meaning of the data depends upon the hint type. The implementation may or may not do - /// anything with these hints. - /// - /// String which the barcode encodes - /// - virtual public Result decode(BinaryBitmap image, IDictionary hints) - { - var result = doDecode(image, hints); - if (result == null) - { - bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER); - bool tryHarderWithoutRotation = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION); - if (tryHarder && !tryHarderWithoutRotation && image.RotateSupported) - { - BinaryBitmap rotatedImage = image.rotateCounterClockwise(); - result = doDecode(rotatedImage, hints); - if (result == null) - return null; - // Record that we found it rotated 90 degrees CCW / 270 degrees CW - IDictionary metadata = result.ResultMetadata; - int orientation = 270; - if (metadata != null && metadata.ContainsKey(ResultMetadataType.ORIENTATION)) - { - // But if we found it reversed in doDecode(), add in that result here: - orientation = (orientation + - (int) metadata[ResultMetadataType.ORIENTATION])%360; - } - result.putMetadata(ResultMetadataType.ORIENTATION, orientation); - // Update result points - ResultPoint[] points = result.ResultPoints; - if (points != null) - { - int height = rotatedImage.Height; - for (int i = 0; i < points.Length; i++) - { - points[i] = new ResultPoint(height - points[i].Y - 1, points[i].X); - } - } - } - } - return result; - } - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - virtual public void reset() - { - // do nothing - } - - /// - /// We're going to examine rows from the middle outward, searching alternately above and below the - /// middle, and farther out each time. rowStep is the number of rows between each successive - /// attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then - /// middle + rowStep, then middle - (2 * rowStep), etc. - /// rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily - /// decided that moving up and down by about 1/16 of the image is pretty good; we try more of the - /// image if "trying harder". - /// - /// The image to decode - /// Any hints that were requested - /// The contents of the decoded barcode - virtual protected Result doDecode(BinaryBitmap image, IDictionary hints) - { - int width = image.Width; - int height = image.Height; - BitArray row = new BitArray(width); - - int middle = height >> 1; - bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER); - int rowStep = Math.Max(1, height >> (tryHarder ? 8 : 5)); - int maxLines; - if (tryHarder) - { - maxLines = height; // Look at the whole image, not just the center - } - else - { - maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image - } - - for (int x = 0; x < maxLines; x++) - { - - // Scanning from the middle out. Determine which row we're looking at next: - int rowStepsAboveOrBelow = (x + 1) >> 1; - bool isAbove = (x & 0x01) == 0; // i.e. is x even? - int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow); - if (rowNumber < 0 || rowNumber >= height) - { - // Oops, if we run off the top or bottom, stop - break; - } - - // Estimate black point for this row and load it: - row = image.getBlackRow(rowNumber, row); - if (row == null) - continue; - - // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to - // handle decoding upside down barcodes. - for (int attempt = 0; attempt < 2; attempt++) - { - if (attempt == 1) - { - // trying again? - row.reverse(); // reverse the row and continue - // This means we will only ever draw result points *once* in the life of this method - // since we want to avoid drawing the wrong points after flipping the row, and, - // don't want to clutter with noise from every single row scan -- just the scans - // that start on the center line. - if (hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK)) - { - IDictionary newHints = new Dictionary(); - foreach (var hint in hints) - { - if (hint.Key != DecodeHintType.NEED_RESULT_POINT_CALLBACK) - newHints.Add(hint.Key, hint.Value); - } - hints = newHints; - } - } - // Look for a barcode - Result result = decodeRow(rowNumber, row, hints); - if (result == null) - continue; - - // We found our barcode - if (attempt == 1) - { - // But it was upside down, so note that - result.putMetadata(ResultMetadataType.ORIENTATION, 180); - // And remember to flip the result points horizontally. - ResultPoint[] points = result.ResultPoints; - if (points != null) - { - points[0] = new ResultPoint(width - points[0].X - 1, points[0].Y); - points[1] = new ResultPoint(width - points[1].X - 1, points[1].Y); - } - } - return result; - } - } - - return null; - } - - /// - /// Records the size of successive runs of white and black pixels in a row, starting at a given point. - /// The values are recorded in the given array, and the number of runs recorded is equal to the size - /// of the array. If the row starts on a white pixel at the given start point, then the first count - /// recorded is the run of white pixels starting from that point; likewise it is the count of a run - /// of black pixels if the row begin on a black pixels at that point. - /// - /// row to count from - /// offset into row to start at - /// array into which to record counts - protected static bool recordPattern(BitArray row, - int start, - int[] counters) - { - return recordPattern(row, start, counters, counters.Length); - } - - /// - /// Records the size of successive runs of white and black pixels in a row, starting at a given point. - /// The values are recorded in the given array, and the number of runs recorded is equal to the size - /// of the array. If the row starts on a white pixel at the given start point, then the first count - /// recorded is the run of white pixels starting from that point; likewise it is the count of a run - /// of black pixels if the row begin on a black pixels at that point. - /// - /// row to count from - /// offset into row to start at - /// array into which to record counts - protected static bool recordPattern(BitArray row, - int start, - int[] counters, - int numCounters) - { - for (int idx = 0; idx < numCounters; idx++) - { - counters[idx] = 0; - } - int end = row.Size; - if (start >= end) - { - return false; - } - bool isWhite = !row[start]; - int counterPosition = 0; - int i = start; - while (i < end) - { - if (row[i] ^ isWhite) - { // that is, exactly one is true - counters[counterPosition]++; - } - else - { - counterPosition++; - if (counterPosition == numCounters) - { - break; - } - else - { - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - i++; - } - // If we read fully the last section of pixels and filled up our counters -- or filled - // the last counter but ran off the side of the image, OK. Otherwise, a problem. - return (counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end)); - } - - /// - /// Records the pattern in reverse. - /// - /// The row. - /// The start. - /// The counters. - /// - protected static bool recordPatternInReverse(BitArray row, int start, int[] counters) - { - // This could be more efficient I guess - int numTransitionsLeft = counters.Length; - bool last = row[start]; - while (start > 0 && numTransitionsLeft >= 0) - { - if (row[--start] != last) - { - numTransitionsLeft--; - last = !last; - } - } - if (numTransitionsLeft >= 0) - { - return false; - } - return recordPattern(row, start + 1, counters); - } - - /// - /// Determines how closely a set of observed counts of runs of black/white values matches a given - /// target pattern. This is reported as the ratio of the total variance from the expected pattern - /// proportions across all pattern elements, to the length of the pattern. - /// - /// observed counters - /// expected pattern - /// The most any counter can differ before we give up - /// ratio of total variance between counters and pattern compared to total pattern size, - /// where the ratio has been multiplied by 256. So, 0 means no variance (perfect match); 256 means - /// the total variance between counters and patterns equals the pattern length, higher values mean - /// even more variance - protected static int patternMatchVariance(int[] counters, - int[] pattern, - int maxIndividualVariance) - { - int numCounters = counters.Length; - int total = 0; - int patternLength = 0; - for (int i = 0; i < numCounters; i++) - { - total += counters[i]; - patternLength += pattern[i]; - } - if (total < patternLength) - { - // If we don't even have one pixel per unit of bar width, assume this is too small - // to reliably match, so fail: - return Int32.MaxValue; - } - // We're going to fake floating-point math in integers. We just need to use more bits. - // Scale up patternLength so that intermediate values below like scaledCounter will have - // more "significant digits" - int unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength; - maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT; - - int totalVariance = 0; - for (int x = 0; x < numCounters; x++) - { - int counter = counters[x] << INTEGER_MATH_SHIFT; - int scaledPattern = pattern[x] * unitBarWidth; - int variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; - if (variance > maxIndividualVariance) - { - return Int32.MaxValue; - } - totalVariance += variance; - } - return totalVariance / total; - } - - /// - /// Attempts to decode a one-dimensional barcode format given a single row of - /// an image. - /// - /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// - /// containing encoded string and start/end of barcode - /// - public abstract Result decodeRow(int rowNumber, BitArray row, IDictionary hints); - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/OneDimensionalCodeWriter.cs b/zxing.core/xx/oned/OneDimensionalCodeWriter.cs deleted file mode 100644 index 062e8dc..0000000 --- a/zxing.core/xx/oned/OneDimensionalCodeWriter.cs +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2011 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Encapsulates functionality and implementation that is common to one-dimensional barcodes.

- /// dsbnatut@gmail.com (Kazuki Nishiura) - ///
- public abstract class OneDimensionalCodeWriter : Writer - { - /// - /// Encode a barcode using the default settings. - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - /// - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - { - return encode(contents, format, width, height, null); - } - - /// - /// Encode the contents following specified format. - /// {@code width} and {@code height} are required size. This method may return bigger size - /// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - /// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - /// or {@code height}, {@code IllegalArgumentException} is thrown. - /// - public virtual BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (String.IsNullOrEmpty(contents)) - { - throw new ArgumentException("Found empty contents"); - } - - if (width < 0 || height < 0) - { - throw new ArgumentException("Negative size is not allowed. Input: " - + width + 'x' + height); - } - - int sidesMargin = DefaultMargin; - if (hints != null) - { - var sidesMarginInt = hints.ContainsKey(EncodeHintType.MARGIN) ? (int)hints[EncodeHintType.MARGIN] : (int?)null; - if (sidesMarginInt != null) - { - sidesMargin = sidesMarginInt.Value; - } - } - - var code = encode(contents); - return renderResult(code, width, height, sidesMargin); - } - - /// - /// - /// a byte array of horizontal pixels (0 = white, 1 = black) - private static BitMatrix renderResult(bool[] code, int width, int height, int sidesMargin) - { - int inputWidth = code.Length; - // Add quiet zone on both sides. - int fullWidth = inputWidth + sidesMargin; - int outputWidth = Math.Max(width, fullWidth); - int outputHeight = Math.Max(1, height); - - int multiple = outputWidth / fullWidth; - int leftPadding = (outputWidth - (inputWidth * multiple)) / 2; - - BitMatrix output = new BitMatrix(outputWidth, outputHeight); - for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) - { - if (code[inputX]) - { - output.setRegion(outputX, 0, multiple, outputHeight); - } - } - return output; - } - - - /// - /// Appends the given pattern to the target array starting at pos. - /// - /// encode black/white pattern into this array - /// position to start encoding at in target - /// lengths of black/white runs to encode - /// starting color - false for white, true for black - /// the number of elements added to target. - protected static int appendPattern(bool[] target, int pos, int[] pattern, bool startColor) - { - bool color = startColor; - int numAdded = 0; - foreach (int len in pattern) - { - for (int j = 0; j < len; j++) - { - target[pos++] = color; - } - numAdded += len; - color = !color; // flip color after each segment - } - return numAdded; - } - - /// - /// Gets the default margin. - /// - virtual public int DefaultMargin - { - get - { - // CodaBar spec requires a side margin to be more than ten times wider than narrow space. - // This seems like a decent idea for a default for all formats. - return 10; - } - } - - /// - /// Encode the contents to bool array expression of one-dimensional barcode. - /// Start code and end code should be included in result, and side margins should not be included. - /// - /// barcode contents to encode - /// a bool[] of horizontal pixels (false = white, true = black) - public abstract bool[] encode(String contents); - - /// - /// Calculates the checksum digit modulo10. - /// - /// The contents. - /// - public static String CalculateChecksumDigitModulo10(String contents) - { - var oddsum = 0; - var evensum = 0; - - for (var index = contents.Length - 1; index >= 0; index -= 2) - { - oddsum += (contents[index] - '0'); - } - for (var index = contents.Length - 2; index >= 0; index -= 2) - { - evensum += (contents[index] - '0'); - } - - return contents + ((10 - ((oddsum * 3 + evensum) % 10)) % 10); - } - } -} diff --git a/zxing.core/xx/oned/PlesseyWriter.cs b/zxing.core/xx/oned/PlesseyWriter.cs deleted file mode 100644 index 6a37e65..0000000 --- a/zxing.core/xx/oned/PlesseyWriter.cs +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2013 ZXing.Net authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders a Plessey code as a . - /// - public sealed class PlesseyWriter : OneDimensionalCodeWriter - { - private const String ALPHABET_STRING = "0123456789ABCDEF"; - private static readonly int[] startWidths = new[] { 14, 11, 14, 11, 5, 20, 14, 11 }; - private static readonly int[] terminationWidths = new[] { 25 }; - private static readonly int[] endWidths = new[] { 20, 5, 20, 5, 14, 11, 14, 11 }; - private static readonly int[][] numberWidths = new[] - { - new[] { 5, 20, 5, 20, 5, 20, 5, 20 }, // 0 - new[] { 14, 11, 5, 20, 5, 20, 5, 20 }, // 1 - new[] { 5, 20, 14, 11, 5, 20, 5, 20 }, // 2 - new[] { 14, 11, 14, 11, 5, 20, 5, 20 }, // 3 - new[] { 5, 20, 5, 20, 14, 11, 5, 20 }, // 4 - new[] { 14, 11, 5, 20, 14, 11, 5, 20 }, // 5 - new[] { 5, 20, 14, 11, 14, 11, 5, 20 }, // 6 - new[] { 14, 11, 14, 11, 14, 11, 5, 20 }, // 7 - new[] { 5, 20, 5, 20, 5, 20, 14, 11 }, // 8 - new[] { 14, 11, 5, 20, 5, 20, 14, 11 }, // 9 - new[] { 5, 20, 14, 11, 5, 20, 14, 11 }, // A / 10 - new[] { 14, 11, 14, 11, 5, 20, 14, 11 }, // B / 11 - new[] { 5, 20, 5, 20, 14, 11, 14, 11 }, // C / 12 - new[] { 14, 11, 5, 20, 14, 11, 14, 11 }, // D / 13 - new[] { 5, 20, 14, 11, 14, 11, 14, 11 }, // E / 14 - new[] { 14, 11, 14, 11, 14, 11, 14, 11 }, // F / 15 - }; - private static readonly byte[] crcGrid = new byte[] { 1, 1, 1, 1, 0, 1, 0, 0, 1 }; - private static readonly int[] crc0Widths = new[] {5, 20}; - private static readonly int[] crc1Widths = new[] {14, 11}; - - /// - /// Encode the contents following specified format. - /// {@code width} and {@code height} are required size. This method may return bigger size - /// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and - /// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width} - /// or {@code height}, {@code IllegalArgumentException} is thrown. - /// - /// - /// - /// - /// - /// - /// - public override BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.PLESSEY) - { - throw new ArgumentException("Can only encode Plessey, but got " + format); - } - return base.encode(contents, format, width, height, hints); - } - - /// - /// Encode the contents to byte array expression of one-dimensional barcode. - /// Start code and end code should be included in result, and side margins should not be included. - /// a {@code boolean[]} of horizontal pixels (false = white, true = black) - /// - /// - /// - override public bool[] encode(String contents) - { - var length = contents.Length; - for (var i = 0; i < length; i++) - { - int indexInString = ALPHABET_STRING.IndexOf(contents[i]); - if (indexInString < 0) - throw new ArgumentException("Requested contents contains a not encodable character: '" + contents[i] + "'"); - } - - // quiet zone + start pattern + data + crc + termination bar + end pattern + quiet zone - var codeWidth = 100 + 100 + length * 100 + 25 * 8 + 25 + 100 + 100; - var result = new bool[codeWidth]; - var crcBuffer = new byte[4*length + 8]; - var crcBufferPos = 0; - var pos = 100; - // start pattern - pos += appendPattern(result, pos, startWidths, true); - // data - for (var i = 0; i < length; i++) - { - var indexInString = ALPHABET_STRING.IndexOf(contents[i]); - var widths = numberWidths[indexInString]; - pos += appendPattern(result, pos, widths, true); - // remember the position number for crc calculation - crcBuffer[crcBufferPos++] = (byte)(indexInString & 1); - crcBuffer[crcBufferPos++] = (byte)((indexInString >> 1) & 1); - crcBuffer[crcBufferPos++] = (byte)((indexInString >> 2) & 1); - crcBuffer[crcBufferPos++] = (byte)((indexInString >> 3) & 1); - } - // CRC calculation - for (var i = 0; i < (4 * length); i++) - { - if (crcBuffer[i] != 0) - { - for (var j = 0; j < 9; j++) - { - crcBuffer[i + j] ^= crcGrid[j]; - } - } - } - // append CRC pattern - for (var i = 0; i < 8; i++) - { - switch (crcBuffer[length * 4 + i]) - { - case 0: - pos += appendPattern(result, pos, crc0Widths, true); - break; - case 1: - pos += appendPattern(result, pos, crc1Widths, true); - break; - } - } - // termination bar - pos += appendPattern(result, pos, terminationWidths, true); - // end pattern - appendPattern(result, pos, endWidths, false); - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCAReader.cs b/zxing.core/xx/oned/UPCAReader.cs deleted file mode 100644 index 2eb1e4c..0000000 --- a/zxing.core/xx/oned/UPCAReader.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Implements decoding of the UPC-A format.

- /// dswitkin@google.com (Daniel Switkin) - /// Sean Owen - ///
- public sealed class UPCAReader : UPCEANReader - { - private readonly UPCEANReader ean13Reader = new EAN13Reader(); - - /// - ///

Like decodeRow(int, BitArray, java.util.Map), but - /// allows caller to inform method about where the UPC/EAN start pattern is - /// found. This allows this to be computed once and reused across many implementations.

- ///
- /// - /// - /// - /// - /// - override public Result decodeRow(int rowNumber, - BitArray row, - int[] startGuardRange, - IDictionary hints) - { - return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange, hints)); - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// - /// containing encoded string and start/end of barcode or null, if an error occurs or barcode cannot be found - /// - override public Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints)); - } - - /// - /// Decodes the specified image. - /// - /// The image. - /// The hints. - /// - override public Result decode(BinaryBitmap image, IDictionary hints) - { - return maybeReturnResult(ean13Reader.decode(image, hints)); - } - - /// - /// Get the format of this decoder. - /// The 1D format. - /// - override internal BarcodeFormat BarcodeFormat - { - get { return BarcodeFormat.UPC_A; } - } - - /// - /// Subclasses override this to decode the portion of a barcode between the start - /// and end guard patterns. - /// - /// row of black/white values to search - /// start/end offset of start guard pattern - /// to append decoded chars to - /// - /// horizontal offset of first pixel after the "middle" that was decoded or -1 if decoding could not complete successfully - /// - override protected internal int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) - { - return ean13Reader.decodeMiddle(row, startRange, resultString); - } - - private static Result maybeReturnResult(Result result) - { - if (result == null) - return null; - - String text = result.Text; - if (text[0] == '0') - { - return new Result(text.Substring(1), null, result.ResultPoints, BarcodeFormat.UPC_A); - } - else - { - return null; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCAWriter.cs b/zxing.core/xx/oned/UPCAWriter.cs deleted file mode 100644 index 3227302..0000000 --- a/zxing.core/xx/oned/UPCAWriter.cs +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2010 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// This object renders a UPC-A code as a . - /// qwandor@google.com (Andrew Walbran) - /// - public class UPCAWriter : Writer - { - private readonly EAN13Writer subWriter = new EAN13Writer(); - - /// - /// Encode a barcode using the default settings. - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - /// - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - { - return encode(contents, format, width, height, null); - } - - /// - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// Additional parameters to supply to the encoder - /// - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - /// - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (format != BarcodeFormat.UPC_A) - { - throw new ArgumentException("Can only encode UPC-A, but got " + format); - } - return subWriter.encode(preencode(contents), BarcodeFormat.EAN_13, width, height, hints); - } - - /// - /// Transform a UPC-A code into the equivalent EAN-13 code, and add a check digit if it is not - /// already present. - /// - private static String preencode(String contents) - { - int length = contents.Length; - if (length == 11) - { - // No check digit present, calculate it and add it - int sum = 0; - for (int i = 0; i < 11; ++i) - { - sum += (contents[i] - '0') * (i % 2 == 0 ? 3 : 1); - } - contents += (1000 - sum) % 10; - } - else if (length != 12) - { - throw new ArgumentException( - "Requested contents should be 11 or 12 digits long, but got " + contents.Length); - } - return '0' + contents; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCEANExtension2Support.cs b/zxing.core/xx/oned/UPCEANExtension2Support.cs deleted file mode 100644 index 8ff4ea6..0000000 --- a/zxing.core/xx/oned/UPCEANExtension2Support.cs +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - /// @see UPCEANExtension5Support - /// - sealed class UPCEANExtension2Support - { - private readonly int[] decodeMiddleCounters = new int[4]; - private readonly StringBuilder decodeRowStringBuffer = new StringBuilder(); - - internal Result decodeRow(int rowNumber, BitArray row, int[] extensionStartRange) - { - StringBuilder result = decodeRowStringBuffer; - result.Length = 0; - int end = decodeMiddle(row, extensionStartRange, result); - if (end < 0) - return null; - - String resultString = result.ToString(); - IDictionary extensionData = parseExtensionString(resultString); - - Result extensionResult = - new Result(resultString, - null, - new ResultPoint[] { - new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0f, (float) rowNumber), - new ResultPoint((float) end, (float) rowNumber), - }, - BarcodeFormat.UPC_EAN_EXTENSION); - if (extensionData != null) - { - extensionResult.putAllMetadata(extensionData); - } - return extensionResult; - } - - int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) - { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.Size; - int rowOffset = startRange[1]; - - int checkParity = 0; - - for (int x = 0; x < 2 && rowOffset < end; x++) - { - int bestMatch; - if (!UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS, out bestMatch)) - return -1; - resultString.Append((char)('0' + bestMatch % 10)); - foreach (int counter in counters) - { - rowOffset += counter; - } - if (bestMatch >= 10) - { - checkParity |= 1 << (1 - x); - } - if (x != 1) - { - // Read off separator if not last - rowOffset = row.getNextSet(rowOffset); - rowOffset = row.getNextUnset(rowOffset); - } - } - - if (resultString.Length != 2) - { - return -1; - } - - if (int.Parse(resultString.ToString()) % 4 != checkParity) - { - return -1; - } - - return rowOffset; - } - - /// - /// Parses the extension string. - /// - /// raw content of extension - /// formatted interpretation of raw content as a {@link Map} mapping - private static IDictionary parseExtensionString(String raw) - { - if (raw.Length != 2) - { - return null; - } - IDictionary result = new Dictionary(); - result[ResultMetadataType.ISSUE_NUMBER] = Convert.ToInt32(raw); - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCEANExtension5Support.cs b/zxing.core/xx/oned/UPCEANExtension5Support.cs deleted file mode 100644 index ba6a6ff..0000000 --- a/zxing.core/xx/oned/UPCEANExtension5Support.cs +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /** - * @see UPCEANExtension2Support - */ - sealed class UPCEANExtension5Support - { - - private static readonly int[] CHECK_DIGIT_ENCODINGS = { - 0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05 - }; - - private readonly int[] decodeMiddleCounters = new int[4]; - private readonly StringBuilder decodeRowStringBuffer = new StringBuilder(); - - internal Result decodeRow(int rowNumber, BitArray row, int[] extensionStartRange) - { - StringBuilder result = decodeRowStringBuffer; - result.Length = 0; - int end = decodeMiddle(row, extensionStartRange, result); - if (end < 0) - return null; - - String resultString = result.ToString(); - IDictionary extensionData = parseExtensionString(resultString); - - Result extensionResult = - new Result(resultString, - null, - new ResultPoint[] { - new ResultPoint((extensionStartRange[0] + extensionStartRange[1]) / 2.0f, (float) rowNumber), - new ResultPoint((float) end, (float) rowNumber), - }, - BarcodeFormat.UPC_EAN_EXTENSION); - if (extensionData != null) - { - extensionResult.putAllMetadata(extensionData); - } - return extensionResult; - } - - int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString) - { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.Size; - int rowOffset = startRange[1]; - - int lgPatternFound = 0; - - for (int x = 0; x < 5 && rowOffset < end; x++) - { - int bestMatch; - if (!UPCEANReader.decodeDigit(row, counters, rowOffset, UPCEANReader.L_AND_G_PATTERNS, out bestMatch)) - return -1; - resultString.Append((char)('0' + bestMatch % 10)); - foreach (int counter in counters) - { - rowOffset += counter; - } - if (bestMatch >= 10) - { - lgPatternFound |= 1 << (4 - x); - } - if (x != 4) - { - // Read off separator if not last - rowOffset = row.getNextSet(rowOffset); - rowOffset = row.getNextUnset(rowOffset); - } - } - - if (resultString.Length != 5) - { - return -1; - } - - int checkDigit; - if (!determineCheckDigit(lgPatternFound, out checkDigit)) - return -1; - - if (extensionChecksum(resultString.ToString()) != checkDigit) - { - return -1; - } - - return rowOffset; - } - - private static int extensionChecksum(String s) - { - int length = s.Length; - int sum = 0; - for (int i = length - 2; i >= 0; i -= 2) - { - sum += (int)s[i] - (int)'0'; - } - sum *= 3; - for (int i = length - 1; i >= 0; i -= 2) - { - sum += (int)s[i] - (int)'0'; - } - sum *= 3; - return sum % 10; - } - - private static bool determineCheckDigit(int lgPatternFound, out int checkDigit) - { - for (checkDigit = 0; checkDigit < 10; checkDigit++) - { - if (lgPatternFound == CHECK_DIGIT_ENCODINGS[checkDigit]) - { - return true; - } - } - return false; - } - - /// - /// Parses the extension string. - /// - /// raw content of extension - /// formatted interpretation of raw content as a {@link Map} mapping - /// one {@link ResultMetadataType} to appropriate value, or {@code null} if not known - private static IDictionary parseExtensionString(String raw) - { - if (raw.Length != 5) - { - return null; - } - Object value = parseExtension5String(raw); - if (value == null) - { - return null; - } - IDictionary result = new Dictionary(); - result[ResultMetadataType.SUGGESTED_PRICE] = value; - return result; - } - - private static String parseExtension5String(String raw) - { - String currency; - switch (raw[0]) - { - case '0': - currency = "£"; - break; - case '5': - currency = "$"; - break; - case '9': - // Reference: http://www.jollytech.com - if ("90000".Equals(raw)) - { - // No suggested retail price - return null; - } - if ("99991".Equals(raw)) - { - // Complementary - return "0.00"; - } - if ("99990".Equals(raw)) - { - return "Used"; - } - // Otherwise... unknown currency? - currency = ""; - break; - default: - currency = ""; - break; - } - int rawAmount = int.Parse(raw.Substring(1)); - String unitsString = (rawAmount / 100).ToString(); - int hundredths = rawAmount % 100; - String hundredthsString = hundredths < 10 ? "0" + hundredths : hundredths.ToString(); - return currency + unitsString + '.' + hundredthsString; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCEANExtensionSupport.cs b/zxing.core/xx/oned/UPCEANExtensionSupport.cs deleted file mode 100644 index 3992bb1..0000000 --- a/zxing.core/xx/oned/UPCEANExtensionSupport.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 ZXing.Common; - -namespace ZXing.OneD -{ - sealed class UPCEANExtensionSupport - { - private static readonly int[] EXTENSION_START_PATTERN = { 1, 1, 2 }; - - private readonly UPCEANExtension2Support twoSupport = new UPCEANExtension2Support(); - private readonly UPCEANExtension5Support fiveSupport = new UPCEANExtension5Support(); - - internal Result decodeRow(int rowNumber, BitArray row, int rowOffset) - { - int[] extensionStartRange = UPCEANReader.findGuardPattern(row, rowOffset, false, EXTENSION_START_PATTERN); - if (extensionStartRange == null) - return null; - var result = fiveSupport.decodeRow(rowNumber, row, extensionStartRange); - if (result == null) - result = twoSupport.decodeRow(rowNumber, row, extensionStartRange); - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCEANReader.cs b/zxing.core/xx/oned/UPCEANReader.cs deleted file mode 100644 index 24942df..0000000 --- a/zxing.core/xx/oned/UPCEANReader.cs +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Encapsulates functionality and implementation that is common to UPC and EAN families - /// of one-dimensional barcodes.

- /// dswitkin@google.com (Daniel Switkin) - /// Sean Owen - /// alasdair@google.com (Alasdair Mackintosh) - ///
- public abstract class UPCEANReader : OneDReader - { - - // These two values are critical for determining how permissive the decoding will be. - // We've arrived at these values through a lot of trial and error. Setting them any higher - // lets false positives creep in quickly. - private static readonly int MAX_AVG_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.48f); - private static readonly int MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f); - - /// - /// Start/end guard pattern. - /// - internal static int[] START_END_PATTERN = { 1, 1, 1, }; - - /// - /// Pattern marking the middle of a UPC/EAN pattern, separating the two halves. - /// - internal static int[] MIDDLE_PATTERN = { 1, 1, 1, 1, 1 }; - - /// - /// "Odd", or "L" patterns used to encode UPC/EAN digits. - /// - internal static int[][] L_PATTERNS = { - new[] {3, 2, 1, 1}, // 0 - new[] {2, 2, 2, 1}, // 1 - new[] {2, 1, 2, 2}, // 2 - new[] {1, 4, 1, 1}, // 3 - new[] {1, 1, 3, 2}, // 4 - new[] {1, 2, 3, 1}, // 5 - new[] {1, 1, 1, 4}, // 6 - new[] {1, 3, 1, 2}, // 7 - new[] {1, 2, 1, 3}, // 8 - new[] {3, 1, 1, 2} // 9 - }; - - /// - /// As above but also including the "even", or "G" patterns used to encode UPC/EAN digits. - /// - internal static int[][] L_AND_G_PATTERNS; - - static UPCEANReader() - { - L_AND_G_PATTERNS = new int[20][]; - Array.Copy(L_PATTERNS, 0, L_AND_G_PATTERNS, 0, 10); - for (int i = 10; i < 20; i++) - { - int[] widths = L_PATTERNS[i - 10]; - int[] reversedWidths = new int[widths.Length]; - for (int j = 0; j < widths.Length; j++) - { - reversedWidths[j] = widths[widths.Length - j - 1]; - } - L_AND_G_PATTERNS[i] = reversedWidths; - } - } - - private readonly StringBuilder decodeRowStringBuffer; - private readonly UPCEANExtensionSupport extensionReader; - private readonly EANManufacturerOrgSupport eanManSupport; - - /// - /// Initializes a new instance of the class. - /// - protected UPCEANReader() - { - decodeRowStringBuffer = new StringBuilder(20); - extensionReader = new UPCEANExtensionSupport(); - eanManSupport = new EANManufacturerOrgSupport(); - } - - internal static int[] findStartGuardPattern(BitArray row) - { - bool foundStart = false; - int[] startRange = null; - int nextStart = 0; - int[] counters = new int[START_END_PATTERN.Length]; - while (!foundStart) - { - for (int idx = 0; idx < START_END_PATTERN.Length; idx++) - counters[idx] = 0; - startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, counters); - if (startRange == null) - return null; - int start = startRange[0]; - nextStart = startRange[1]; - // Make sure there is a quiet zone at least as big as the start pattern before the barcode. - // If this check would run off the left edge of the image, do not accept this barcode, - // as it is very likely to be a false positive. - int quietStart = start - (nextStart - start); - if (quietStart >= 0) - { - foundStart = row.isRange(quietStart, start, false); - } - } - return startRange; - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// - /// containing encoded string and start/end of barcode or null, if an error occurs or barcode cannot be found - /// - override public Result decodeRow(int rowNumber, BitArray row, IDictionary hints) - { - return decodeRow(rowNumber, row, findStartGuardPattern(row), hints); - } - - /// - ///

Like decodeRow(int, BitArray, java.util.Map), but - /// allows caller to inform method about where the UPC/EAN start pattern is - /// found. This allows this to be computed once and reused across many implementations.

- ///
- /// row index into the image - /// encoding of the row of the barcode image - /// start/end column where the opening start pattern was found - /// optional hints that influence decoding - /// encapsulating the result of decoding a barcode in the row - virtual public Result decodeRow(int rowNumber, - BitArray row, - int[] startGuardRange, - IDictionary hints) - { - var resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : - (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint( - (startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber - )); - } - - var result = decodeRowStringBuffer; - result.Length = 0; - var endStart = decodeMiddle(row, startGuardRange, result); - if (endStart < 0) - return null; - - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint( - endStart, rowNumber - )); - } - - var endRange = decodeEnd(row, endStart); - if (endRange == null) - return null; - - if (resultPointCallback != null) - { - resultPointCallback(new ResultPoint( - (endRange[0] + endRange[1]) / 2.0f, rowNumber - )); - } - - - // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The - // spec might want more whitespace, but in practice this is the maximum we can count on. - var end = endRange[1]; - var quietEnd = end + (end - endRange[0]); - if (quietEnd >= row.Size || !row.isRange(end, quietEnd, false)) - { - return null; - } - - var resultString = result.ToString(); - // UPC/EAN should never be less than 8 chars anyway - if (resultString.Length < 8) - { - return null; - } - if (!checkChecksum(resultString)) - { - return null; - } - - var left = (startGuardRange[1] + startGuardRange[0]) / 2.0f; - var right = (endRange[1] + endRange[0]) / 2.0f; - var format = BarcodeFormat; - var decodeResult = new Result(resultString, - null, // no natural byte representation for these barcodes - new ResultPoint[] - { - new ResultPoint(left, rowNumber), - new ResultPoint(right, rowNumber) - }, - format); - - var extensionResult = extensionReader.decodeRow(rowNumber, row, endRange[1]); - if (extensionResult != null) - { - decodeResult.putMetadata(ResultMetadataType.UPC_EAN_EXTENSION, extensionResult.Text); - decodeResult.putAllMetadata(extensionResult.ResultMetadata); - decodeResult.addResultPoints(extensionResult.ResultPoints); - int extensionLength = extensionResult.Text.Length; - int[] allowedExtensions = hints != null && hints.ContainsKey(DecodeHintType.ALLOWED_EAN_EXTENSIONS) ? - (int[]) hints[DecodeHintType.ALLOWED_EAN_EXTENSIONS] : null; - if (allowedExtensions != null) - { - bool valid = false; - foreach (int length in allowedExtensions) - { - if (extensionLength == length) - { - valid = true; - break; - } - } - if (!valid) - { - return null; - } - } - } - - if (format == BarcodeFormat.EAN_13 || format == BarcodeFormat.UPC_A) - { - String countryID = eanManSupport.lookupCountryIdentifier(resultString); - if (countryID != null) - { - decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID); - } - } - - return decodeResult; - } - - /// - /// - /// string of digits to check - /// see - virtual protected bool checkChecksum(String s) - { - return checkStandardUPCEANChecksum(s); - } - - /// - /// Computes the UPC/EAN checksum on a string of digits, and reports - /// whether the checksum is correct or not. - /// - /// string of digits to check - /// true iff string of digits passes the UPC/EAN checksum algorithm - internal static bool checkStandardUPCEANChecksum(String s) - { - int length = s.Length; - if (length == 0) - { - return false; - } - - int sum = 0; - for (int i = length - 2; i >= 0; i -= 2) - { - int digit = (int)s[i] - (int)'0'; - if (digit < 0 || digit > 9) - { - return false; - } - sum += digit; - } - sum *= 3; - for (int i = length - 1; i >= 0; i -= 2) - { - int digit = (int)s[i] - (int)'0'; - if (digit < 0 || digit > 9) - { - return false; - } - sum += digit; - } - return sum % 10 == 0; - } - - /// - /// Decodes the end. - /// - /// The row. - /// The end start. - /// - virtual protected int[] decodeEnd(BitArray row, int endStart) - { - return findGuardPattern(row, endStart, false, START_END_PATTERN); - } - - internal static int[] findGuardPattern(BitArray row, - int rowOffset, - bool whiteFirst, - int[] pattern) - { - return findGuardPattern(row, rowOffset, whiteFirst, pattern, new int[pattern.Length]); - } - - /// - /// - /// row of black/white values to search - /// position to start search - /// if true, indicates that the pattern specifies white/black/white/... - /// pixel counts, otherwise, it is interpreted as black/white/black/... - /// pattern of counts of number of black and white pixels that are being - /// searched for as a pattern - /// array of counters, as long as pattern, to re-use - /// start/end horizontal offset of guard pattern, as an array of two ints - internal static int[] findGuardPattern(BitArray row, - int rowOffset, - bool whiteFirst, - int[] pattern, - int[] counters) - { - int patternLength = pattern.Length; - int width = row.Size; - bool isWhite = whiteFirst; - rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset); - int counterPosition = 0; - int patternStart = rowOffset; - for (int x = rowOffset; x < width; x++) - { - if (row[x] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) - { - return new int[] { patternStart, x }; - } - patternStart += counters[0] + counters[1]; - Array.Copy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - /// - /// Attempts to decode a single UPC/EAN-encoded digit. - /// - /// row of black/white values to decode - /// the counts of runs of observed black/white/black/... values - /// horizontal offset to start decoding from - /// the set of patterns to use to decode -- sometimes different encodings - /// for the digits 0-9 are used, and this indicates the encodings for 0 to 9 that should - /// be used - /// horizontal offset of first pixel beyond the decoded digit - internal static bool decodeDigit(BitArray row, int[] counters, int rowOffset, int[][] patterns, out int digit) - { - digit = -1; - - if (!recordPattern(row, rowOffset, counters)) - return false; - - int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept - int max = patterns.Length; - for (int i = 0; i < max; i++) - { - int[] pattern = patterns[i]; - int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE); - if (variance < bestVariance) - { - bestVariance = variance; - digit = i; - } - } - return digit >= 0; - } - - /// - /// Get the format of this decoder. - /// - /// The 1D format. - internal abstract BarcodeFormat BarcodeFormat { get; } - - /// - /// Subclasses override this to decode the portion of a barcode between the start - /// and end guard patterns. - /// - /// row of black/white values to search - /// start/end offset of start guard pattern - /// to append decoded chars to - /// horizontal offset of first pixel after the "middle" that was decoded or -1 if decoding could not complete successfully - protected internal abstract int decodeMiddle(BitArray row, - int[] startRange, - StringBuilder resultString); - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCEANWriter.cs b/zxing.core/xx/oned/UPCEANWriter.cs deleted file mode 100644 index b56475b..0000000 --- a/zxing.core/xx/oned/UPCEANWriter.cs +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace ZXing.OneD -{ - /// - ///

Encapsulates functionality and implementation that is common to UPC and EAN families - /// of one-dimensional barcodes.

- /// aripollak@gmail.com (Ari Pollak) - /// dsbnatut@gmail.com (Kazuki Nishiura) - ///
- public abstract class UPCEANWriter : OneDimensionalCodeWriter - { - /// - /// Gets the default margin. - /// - public override int DefaultMargin - { - get - { - // Use a different default more appropriate for UPC/EAN - return UPCEANReader.START_END_PATTERN.Length; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/UPCEReader.cs b/zxing.core/xx/oned/UPCEReader.cs deleted file mode 100644 index 10d61e5..0000000 --- a/zxing.core/xx/oned/UPCEReader.cs +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Text; - -using ZXing.Common; - -namespace ZXing.OneD -{ - /// - ///

Implements decoding of the UPC-E format.

- ///

Thisis a great reference for - /// UPC-E information.

- /// Sean Owen - ///
- public sealed class UPCEReader : UPCEANReader - { - /// - /// The pattern that marks the middle, and end, of a UPC-E pattern. - /// There is no "second half" to a UPC-E barcode. - /// - private static readonly int[] MIDDLE_END_PATTERN = { 1, 1, 1, 1, 1, 1 }; - - /// - /// See L_AND_G_PATTERNS these values similarly represent patterns of - /// even-odd parity encodings of digits that imply both the number system (0 or 1) - /// used, and the check digit. - /// - private static readonly int[][] NUMSYS_AND_CHECK_DIGIT_PATTERNS = { - new[] { 0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25 }, - new[] { 0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A } - }; - - private readonly int[] decodeMiddleCounters; - - /// - /// Initializes a new instance of the class. - /// - public UPCEReader() - { - decodeMiddleCounters = new int[4]; - } - - /// - /// Decodes the middle. - /// - /// The row. - /// The start range. - /// The result. - /// - override internal protected int decodeMiddle(BitArray row, int[] startRange, StringBuilder result) - { - int[] counters = decodeMiddleCounters; - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - int end = row.Size; - int rowOffset = startRange[1]; - - int lgPatternFound = 0; - - for (int x = 0; x < 6 && rowOffset < end; x++) - { - int bestMatch; - if (!decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS, out bestMatch)) - return -1; - result.Append((char)('0' + bestMatch % 10)); - foreach (int counter in counters) - { - rowOffset += counter; - } - if (bestMatch >= 10) - { - lgPatternFound |= 1 << (5 - x); - } - } - - if (!determineNumSysAndCheckDigit(result, lgPatternFound)) - return -1; - - return rowOffset; - } - - /// - /// Decodes the end. - /// - /// The row. - /// The end start. - /// - override protected int[] decodeEnd(BitArray row, int endStart) - { - return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN); - } - - /// - /// see checkStandardUPCEANChecksum(String) - /// - /// - /// - override protected bool checkChecksum(String s) - { - return base.checkChecksum(convertUPCEtoUPCA(s)); - } - - /// - /// Determines the num sys and check digit. - /// - /// The result string. - /// The lg pattern found. - /// - private static bool determineNumSysAndCheckDigit(StringBuilder resultString, int lgPatternFound) - { - - for (int numSys = 0; numSys <= 1; numSys++) - { - for (int d = 0; d < 10; d++) - { - if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d]) - { - resultString.Insert(0, new[] { (char)('0' + numSys) }); - resultString.Append((char)('0' + d)); - return true; - } - } - } - return false; - } - - /// - /// Get the format of this decoder. - /// The 1D format. - /// - override internal BarcodeFormat BarcodeFormat - { - get { return BarcodeFormat.UPC_E; } - } - - /// - /// Expands a UPC-E value back into its full, equivalent UPC-A code value. - /// - /// UPC-E code as string of digits - /// equivalent UPC-A code as string of digits - /// - public static String convertUPCEtoUPCA(String upce) - { - var upceChars = upce.Substring(1, 6); - StringBuilder result = new StringBuilder(12); - result.Append(upce[0]); - char lastChar = upceChars[5]; - switch (lastChar) - { - case '0': - case '1': - case '2': - result.Append(upceChars, 0, 2); - result.Append(lastChar); - result.Append("0000"); - result.Append(upceChars, 2, 3); - break; - case '3': - result.Append(upceChars, 0, 3); - result.Append("00000"); - result.Append(upceChars, 3, 2); - break; - case '4': - result.Append(upceChars, 0, 4); - result.Append("00000"); - result.Append(upceChars[4]); - break; - default: - result.Append(upceChars, 0, 5); - result.Append("0000"); - result.Append(lastChar); - break; - } - result.Append(upce[7]); - return result.ToString(); - } - } -} diff --git a/zxing.core/xx/oned/rss/AbstractRSSReader.cs b/zxing.core/xx/oned/rss/AbstractRSSReader.cs deleted file mode 100644 index 89ffa71..0000000 --- a/zxing.core/xx/oned/rss/AbstractRSSReader.cs +++ /dev/null @@ -1,216 +0,0 @@ -/* - * 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; - -namespace ZXing.OneD.RSS -{ - /// - /// - /// - public abstract class AbstractRSSReader : OneDReader - { - private static readonly int MAX_AVG_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.2f); - private static readonly int MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.45f); - - private const float MIN_FINDER_PATTERN_RATIO = 9.5f / 12.0f; - private const float MAX_FINDER_PATTERN_RATIO = 12.5f / 14.0f; - - private readonly int[] decodeFinderCounters; - private readonly int[] dataCharacterCounters; - private readonly float[] oddRoundingErrors; - private readonly float[] evenRoundingErrors; - private readonly int[] oddCounts; - private readonly int[] evenCounts; - - /// - /// Initializes a new instance of the class. - /// - protected AbstractRSSReader() - { - decodeFinderCounters = new int[4]; - dataCharacterCounters = new int[8]; - oddRoundingErrors = new float[4]; - evenRoundingErrors = new float[4]; - oddCounts = new int[dataCharacterCounters.Length / 2]; - evenCounts = new int[dataCharacterCounters.Length / 2]; - } - - /// - /// Gets the decode finder counters. - /// - /// - protected int[] getDecodeFinderCounters() - { - return decodeFinderCounters; - } - - /// - /// Gets the data character counters. - /// - /// - protected int[] getDataCharacterCounters() - { - return dataCharacterCounters; - } - - /// - /// Gets the odd rounding errors. - /// - /// - protected float[] getOddRoundingErrors() - { - return oddRoundingErrors; - } - - /// - /// Gets the even rounding errors. - /// - /// - protected float[] getEvenRoundingErrors() - { - return evenRoundingErrors; - } - - /// - /// Gets the odd counts. - /// - /// - protected int[] getOddCounts() - { - return oddCounts; - } - - /// - /// Gets the even counts. - /// - /// - protected int[] getEvenCounts() - { - return evenCounts; - } - - /// - /// Parses the finder value. - /// - /// The counters. - /// The finder patterns. - /// The value. - /// - protected static bool parseFinderValue(int[] counters, - int[][] finderPatterns, - out int value) - { - for (value = 0; value < finderPatterns.Length; value++) - { - if (patternMatchVariance(counters, finderPatterns[value], MAX_INDIVIDUAL_VARIANCE) < - MAX_AVG_VARIANCE) - { - return true; - } - } - return false; - } - - /// - /// Counts the specified array. - /// - /// The array. - /// - protected static int count(int[] array) - { - int count = 0; - foreach (int a in array) - { - count += a; - } - return count; - } - - /// - /// Increments the specified array. - /// - /// The array. - /// The errors. - protected static void increment(int[] array, float[] errors) - { - int index = 0; - float biggestError = errors[0]; - for (int i = 1; i < array.Length; i++) - { - if (errors[i] > biggestError) - { - biggestError = errors[i]; - index = i; - } - } - array[index]++; - } - - /// - /// Decrements the specified array. - /// - /// The array. - /// The errors. - protected static void decrement(int[] array, float[] errors) - { - int index = 0; - float biggestError = errors[0]; - for (int i = 1; i < array.Length; i++) - { - if (errors[i] < biggestError) - { - biggestError = errors[i]; - index = i; - } - } - array[index]--; - } - - /// - /// Determines whether [is finder pattern] [the specified counters]. - /// - /// The counters. - /// - /// true if [is finder pattern] [the specified counters]; otherwise, false. - /// - protected static bool isFinderPattern(int[] counters) - { - int firstTwoSum = counters[0] + counters[1]; - int sum = firstTwoSum + counters[2] + counters[3]; - float ratio = (float)firstTwoSum / (float)sum; - if (ratio >= MIN_FINDER_PATTERN_RATIO && ratio <= MAX_FINDER_PATTERN_RATIO) - { - // passes ratio test in spec, but see if the counts are unreasonable - int minCounter = Int32.MaxValue; - int maxCounter = Int32.MinValue; - foreach (int counter in counters) - { - if (counter > maxCounter) - { - maxCounter = counter; - } - if (counter < minCounter) - { - minCounter = counter; - } - } - return maxCounter < 10 * minCounter; - } - return false; - } - } -} diff --git a/zxing.core/xx/oned/rss/DataCharacter.cs b/zxing.core/xx/oned/rss/DataCharacter.cs deleted file mode 100644 index c0601bf..0000000 --- a/zxing.core/xx/oned/rss/DataCharacter.cs +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.OneD.RSS -{ - /// - /// - /// - public class DataCharacter - { - /// - /// Gets the value. - /// - public int Value { get; private set; } - /// - /// Gets the checksum portion. - /// - public int ChecksumPortion { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The value. - /// The checksum portion. - public DataCharacter(int value, int checksumPortion) - { - Value = value; - ChecksumPortion = checksumPortion; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - override public String ToString() - { - return Value + "(" + ChecksumPortion + ')'; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - override public bool Equals(Object o) - { - if (!(o is DataCharacter)) - { - return false; - } - DataCharacter that = (DataCharacter)o; - return Value == that.Value && ChecksumPortion == that.ChecksumPortion; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - override public int GetHashCode() - { - return Value ^ ChecksumPortion; - } - } -} diff --git a/zxing.core/xx/oned/rss/FinderPattern.cs b/zxing.core/xx/oned/rss/FinderPattern.cs deleted file mode 100644 index 4e8259c..0000000 --- a/zxing.core/xx/oned/rss/FinderPattern.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.OneD.RSS -{ - /// - /// - /// - public sealed class FinderPattern - { - /// - /// Gets the value. - /// - public int Value { get; private set; } - /// - /// Gets the start end. - /// - public int[] StartEnd { get; private set; } - /// - /// Gets the result points. - /// - public ResultPoint[] ResultPoints { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// The value. - /// The start end. - /// The start. - /// The end. - /// The row number. - public FinderPattern(int value, int[] startEnd, int start, int end, int rowNumber) - { - Value = value; - StartEnd = startEnd; - ResultPoints = new ResultPoint[] - { - new ResultPoint(start, rowNumber), - new ResultPoint(end, rowNumber), - }; - } - - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - override public bool Equals(Object o) - { - if (!(o is FinderPattern)) - { - return false; - } - FinderPattern that = (FinderPattern)o; - return Value == that.Value; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - override public int GetHashCode() - { - return Value; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/rss/Pair.cs b/zxing.core/xx/oned/rss/Pair.cs deleted file mode 100644 index c8f79d9..0000000 --- a/zxing.core/xx/oned/rss/Pair.cs +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace ZXing.OneD.RSS -{ - internal sealed class Pair : DataCharacter - { - public FinderPattern FinderPattern { get; private set; } - public int Count { get; private set; } - - internal Pair(int value, int checksumPortion, FinderPattern finderPattern) - : base(value, checksumPortion) - { - FinderPattern = finderPattern; - } - - public void incrementCount() - { - Count++; - } - } -} diff --git a/zxing.core/xx/oned/rss/RSS14Reader.cs b/zxing.core/xx/oned/rss/RSS14Reader.cs deleted file mode 100644 index b72af15..0000000 --- a/zxing.core/xx/oned/rss/RSS14Reader.cs +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; -using System.Text; -using ZXing.Common; - -namespace ZXing.OneD.RSS -{ - /// - /// Decodes RSS-14, including truncated and stacked variants. See ISO/IEC 24724:2006. - /// - public sealed class RSS14Reader : AbstractRSSReader - { - private static readonly int[] OUTSIDE_EVEN_TOTAL_SUBSET = { 1, 10, 34, 70, 126 }; - private static readonly int[] INSIDE_ODD_TOTAL_SUBSET = { 4, 20, 48, 81 }; - private static readonly int[] OUTSIDE_GSUM = { 0, 161, 961, 2015, 2715 }; - private static readonly int[] INSIDE_GSUM = { 0, 336, 1036, 1516 }; - private static readonly int[] OUTSIDE_ODD_WIDEST = { 8, 6, 4, 3, 1 }; - private static readonly int[] INSIDE_ODD_WIDEST = { 2, 4, 6, 8 }; - - private static readonly int[][] FINDER_PATTERNS = { - new[] {3, 8, 2, 1}, - new[] {3, 5, 5, 1}, - new[] {3, 3, 7, 1}, - new[] {3, 1, 9, 1}, - new[] {2, 7, 4, 1}, - new[] {2, 5, 6, 1}, - new[] {2, 3, 8, 1}, - new[] {1, 5, 7, 1}, - new[] {1, 3, 9, 1}, - }; - - private readonly List possibleLeftPairs; - private readonly List possibleRightPairs; - - /// - /// Initializes a new instance of the class. - /// - public RSS14Reader() - { - possibleLeftPairs = new List(); - possibleRightPairs = new List(); - } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

- ///
- /// row number from top of the row - /// the black/white pixel data of the row - /// decode hints - /// - /// containing encoded string and start/end of barcode or null, if an error occurs or barcode cannot be found - /// - override public Result decodeRow(int rowNumber, - BitArray row, - IDictionary hints) - { - Pair leftPair = decodePair(row, false, rowNumber, hints); - addOrTally(possibleLeftPairs, leftPair); - row.reverse(); - Pair rightPair = decodePair(row, true, rowNumber, hints); - addOrTally(possibleRightPairs, rightPair); - row.reverse(); - int lefSize = possibleLeftPairs.Count; - for (int i = 0; i < lefSize; i++) - { - Pair left = possibleLeftPairs[i]; - if (left.Count > 1) - { - int rightSize = possibleRightPairs.Count; - for (int j = 0; j < rightSize; j++) - { - Pair right = possibleRightPairs[j]; - if (right.Count > 1) - { - if (checkChecksum(left, right)) - { - return constructResult(left, right); - } - } - } - } - } - return null; - } - - private static void addOrTally(IList possiblePairs, Pair pair) - { - if (pair == null) - { - return; - } - bool found = false; - foreach (Pair other in possiblePairs) - { - if (other.Value == pair.Value) - { - other.incrementCount(); - found = true; - break; - } - } - if (!found) - { - possiblePairs.Add(pair); - } - } - - /// - /// Resets this instance. - /// - public override void reset() - { - possibleLeftPairs.Clear(); - possibleRightPairs.Clear(); - } - - private static Result constructResult(Pair leftPair, Pair rightPair) - { - long symbolValue = 4537077L * leftPair.Value + rightPair.Value; - String text = symbolValue.ToString(); - - StringBuilder buffer = new StringBuilder(14); - for (int i = 13 - text.Length; i > 0; i--) - { - buffer.Append('0'); - } - buffer.Append(text); - - int checkDigit = 0; - for (int i = 0; i < 13; i++) - { - int digit = buffer[i] - '0'; - checkDigit += (i & 0x01) == 0 ? 3 * digit : digit; - } - checkDigit = 10 - (checkDigit % 10); - if (checkDigit == 10) - { - checkDigit = 0; - } - buffer.Append(checkDigit); - - ResultPoint[] leftPoints = leftPair.FinderPattern.ResultPoints; - ResultPoint[] rightPoints = rightPair.FinderPattern.ResultPoints; - return new Result( - buffer.ToString(), - null, - new ResultPoint[] { leftPoints[0], leftPoints[1], rightPoints[0], rightPoints[1], }, - BarcodeFormat.RSS_14); - } - - private static bool checkChecksum(Pair leftPair, Pair rightPair) - { - //int leftFPValue = leftPair.FinderPattern.Value; - //int rightFPValue = rightPair.FinderPattern.Value; - //if ((leftFPValue == 0 && rightFPValue == 8) || - // (leftFPValue == 8 && rightFPValue == 0)) - //{ - //} - int checkValue = (leftPair.ChecksumPortion + 16 * rightPair.ChecksumPortion) % 79; - int targetCheckValue = - 9 * leftPair.FinderPattern.Value + rightPair.FinderPattern.Value; - if (targetCheckValue > 72) - { - targetCheckValue--; - } - if (targetCheckValue > 8) - { - targetCheckValue--; - } - return checkValue == targetCheckValue; - } - - private Pair decodePair(BitArray row, bool right, int rowNumber, IDictionary hints) - { - int[] startEnd = findFinderPattern(row, 0, right); - if (startEnd == null) - return null; - FinderPattern pattern = parseFoundFinderPattern(row, rowNumber, right, startEnd); - if (pattern == null) - return null; - - ResultPointCallback resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : - (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - - if (resultPointCallback != null) - { - float center = (startEnd[0] + startEnd[1]) / 2.0f; - if (right) - { - // row is actually reversed - center = row.Size - 1 - center; - } - resultPointCallback(new ResultPoint(center, rowNumber)); - } - - DataCharacter outside = decodeDataCharacter(row, pattern, true); - if (outside == null) - return null; - DataCharacter inside = decodeDataCharacter(row, pattern, false); - if (inside == null) - return null; - return new Pair(1597*outside.Value + inside.Value, - outside.ChecksumPortion + 4*inside.ChecksumPortion, - pattern); - } - - private DataCharacter decodeDataCharacter(BitArray row, FinderPattern pattern, bool outsideChar) - { - int[] counters = getDataCharacterCounters(); - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - counters[4] = 0; - counters[5] = 0; - counters[6] = 0; - counters[7] = 0; - - if (outsideChar) - { - recordPatternInReverse(row, pattern.StartEnd[0], counters); - } - else - { - recordPattern(row, pattern.StartEnd[1] + 1, counters); - // reverse it - for (int i = 0, j = counters.Length - 1; i < j; i++, j--) - { - int temp = counters[i]; - counters[i] = counters[j]; - counters[j] = temp; - } - } - - int numModules = outsideChar ? 16 : 15; - float elementWidth = (float)count(counters) / (float)numModules; - - int[] oddCounts = this.getOddCounts(); - int[] evenCounts = this.getEvenCounts(); - float[] oddRoundingErrors = this.getOddRoundingErrors(); - float[] evenRoundingErrors = this.getEvenRoundingErrors(); - - for (int i = 0; i < counters.Length; i++) - { - float value = (float)counters[i] / elementWidth; - int rounded = (int)(value + 0.5f); // Round - if (rounded < 1) - { - rounded = 1; - } - else if (rounded > 8) - { - rounded = 8; - } - int offset = i >> 1; - if ((i & 0x01) == 0) - { - oddCounts[offset] = rounded; - oddRoundingErrors[offset] = value - rounded; - } - else - { - evenCounts[offset] = rounded; - evenRoundingErrors[offset] = value - rounded; - } - } - - if (!adjustOddEvenCounts(outsideChar, numModules)) - return null; - - int oddSum = 0; - int oddChecksumPortion = 0; - for (int i = oddCounts.Length - 1; i >= 0; i--) - { - oddChecksumPortion *= 9; - oddChecksumPortion += oddCounts[i]; - oddSum += oddCounts[i]; - } - int evenChecksumPortion = 0; - int evenSum = 0; - for (int i = evenCounts.Length - 1; i >= 0; i--) - { - evenChecksumPortion *= 9; - evenChecksumPortion += evenCounts[i]; - evenSum += evenCounts[i]; - } - int checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion; - - if (outsideChar) - { - if ((oddSum & 0x01) != 0 || oddSum > 12 || oddSum < 4) - { - return null; - } - int group = (12 - oddSum) / 2; - int oddWidest = OUTSIDE_ODD_WIDEST[group]; - int evenWidest = 9 - oddWidest; - int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, false); - int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, true); - int tEven = OUTSIDE_EVEN_TOTAL_SUBSET[group]; - int gSum = OUTSIDE_GSUM[group]; - return new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion); - } - else - { - if ((evenSum & 0x01) != 0 || evenSum > 10 || evenSum < 4) - { - return null; - } - int group = (10 - evenSum) / 2; - int oddWidest = INSIDE_ODD_WIDEST[group]; - int evenWidest = 9 - oddWidest; - int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true); - int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false); - int tOdd = INSIDE_ODD_TOTAL_SUBSET[group]; - int gSum = INSIDE_GSUM[group]; - return new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion); - } - } - - private int[] findFinderPattern(BitArray row, int rowOffset, bool rightFinderPattern) - { - - int[] counters = getDecodeFinderCounters(); - counters[0] = 0; - counters[1] = 0; - counters[2] = 0; - counters[3] = 0; - - int width = row.Size; - bool isWhite = false; - while (rowOffset < width) - { - isWhite = !row[rowOffset]; - if (rightFinderPattern == isWhite) - { - // Will encounter white first when searching for right finder pattern - break; - } - rowOffset++; - } - - int counterPosition = 0; - int patternStart = rowOffset; - for (int x = rowOffset; x < width; x++) - { - if (row[x] ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == 3) - { - if (isFinderPattern(counters)) - { - return new int[] { patternStart, x }; - } - patternStart += counters[0] + counters[1]; - counters[0] = counters[2]; - counters[1] = counters[3]; - counters[2] = 0; - counters[3] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - return null; - } - - private FinderPattern parseFoundFinderPattern(BitArray row, int rowNumber, bool right, int[] startEnd) - { - // Actually we found elements 2-5 - bool firstIsBlack = row[startEnd[0]]; - int firstElementStart = startEnd[0] - 1; - // Locate element 1 - while (firstElementStart >= 0 && firstIsBlack ^ row[firstElementStart]) - { - firstElementStart--; - } - firstElementStart++; - int firstCounter = startEnd[0] - firstElementStart; - // Make 'counters' hold 1-4 - int[] counters = getDecodeFinderCounters(); - Array.Copy(counters, 0, counters, 1, counters.Length - 1); - counters[0] = firstCounter; - int value; - if (!parseFinderValue(counters, FINDER_PATTERNS, out value)) - return null; - int start = firstElementStart; - int end = startEnd[1]; - if (right) - { - // row is actually reversed - start = row.Size - 1 - start; - end = row.Size - 1 - end; - } - return new FinderPattern(value, new int[] { firstElementStart, startEnd[1] }, start, end, rowNumber); - } - - private bool adjustOddEvenCounts(bool outsideChar, int numModules) - { - int oddSum = count(getOddCounts()); - int evenSum = count(getEvenCounts()); - int mismatch = oddSum + evenSum - numModules; - bool oddParityBad = (oddSum & 0x01) == (outsideChar ? 1 : 0); - bool evenParityBad = (evenSum & 0x01) == 1; - - bool incrementOdd = false; - bool decrementOdd = false; - bool incrementEven = false; - bool decrementEven = false; - - if (outsideChar) - { - if (oddSum > 12) - { - decrementOdd = true; - } - else if (oddSum < 4) - { - incrementOdd = true; - } - if (evenSum > 12) - { - decrementEven = true; - } - else if (evenSum < 4) - { - incrementEven = true; - } - } - else - { - if (oddSum > 11) - { - decrementOdd = true; - } - else if (oddSum < 5) - { - incrementOdd = true; - } - if (evenSum > 10) - { - decrementEven = true; - } - else if (evenSum < 4) - { - incrementEven = true; - } - } - - /*if (mismatch == 2) { - if (!(oddParityBad && evenParityBad)) { - throw ReaderException.Instance; - } - decrementOdd = true; - decrementEven = true; - } else if (mismatch == -2) { - if (!(oddParityBad && evenParityBad)) { - throw ReaderException.Instance; - } - incrementOdd = true; - incrementEven = true; - } else */ - if (mismatch == 1) - { - if (oddParityBad) - { - if (evenParityBad) - { - return false; - } - decrementOdd = true; - } - else - { - if (!evenParityBad) - { - return false; - } - decrementEven = true; - } - } - else if (mismatch == -1) - { - if (oddParityBad) - { - if (evenParityBad) - { - return false; - } - incrementOdd = true; - } - else - { - if (!evenParityBad) - { - return false; - } - incrementEven = true; - } - } - else if (mismatch == 0) - { - if (oddParityBad) - { - if (!evenParityBad) - { - return false; - } - // Both bad - if (oddSum < evenSum) - { - incrementOdd = true; - decrementEven = true; - } - else - { - decrementOdd = true; - incrementEven = true; - } - } - else - { - if (evenParityBad) - { - return false; - } - // Nothing to do! - } - } - else - { - return false; - } - - if (incrementOdd) - { - if (decrementOdd) - { - return false; - } - increment(getOddCounts(), getOddRoundingErrors()); - } - if (decrementOdd) - { - decrement(getOddCounts(), getOddRoundingErrors()); - } - if (incrementEven) - { - if (decrementEven) - { - return false; - } - increment(getEvenCounts(), getOddRoundingErrors()); - } - if (decrementEven) - { - decrement(getEvenCounts(), getEvenRoundingErrors()); - } - - return true; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/rss/RSSUtils.cs b/zxing.core/xx/oned/rss/RSSUtils.cs deleted file mode 100644 index 37c5d27..0000000 --- a/zxing.core/xx/oned/rss/RSSUtils.cs +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace ZXing.OneD.RSS -{ - /// - /// Adapted from listings in ISO/IEC 24724 Appendix B and Appendix G. - /// - public static class RSSUtils - { - /* - /// - /// Gets the RS swidths. - /// - /// The val. - /// The n. - /// The elements. - /// Width of the max. - /// if set to true [no narrow]. - /// - public static int[] getRSSwidths(int val, int n, int elements, int maxWidth, bool noNarrow) - { - int[] widths = new int[elements]; - int bar; - int narrowMask = 0; - for (bar = 0; bar < elements - 1; bar++) - { - narrowMask |= 1 << bar; - int elmWidth = 1; - int subVal; - while (true) - { - subVal = combins(n - elmWidth - 1, elements - bar - 2); - if (noNarrow && (narrowMask == 0) && - (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) - { - subVal -= combins(n - elmWidth - (elements - bar), elements - bar - 2); - } - if (elements - bar - 1 > 1) - { - int lessVal = 0; - for (int mxwElement = n - elmWidth - (elements - bar - 2); - mxwElement > maxWidth; - mxwElement--) - { - lessVal += combins(n - elmWidth - mxwElement - 1, elements - bar - 3); - } - subVal -= lessVal * (elements - 1 - bar); - } - else if (n - elmWidth > maxWidth) - { - subVal--; - } - val -= subVal; - if (val < 0) - { - break; - } - elmWidth++; - narrowMask &= ~(1 << bar); - } - val += subVal; - n -= elmWidth; - widths[bar] = elmWidth; - } - widths[bar] = n; - return widths; - } - */ - - /// - /// Gets the RS svalue. - /// - /// The widths. - /// Width of the max. - /// if set to true [no narrow]. - /// - public static int getRSSvalue(int[] widths, int maxWidth, bool noNarrow) - { - int elements = widths.Length; - int n = 0; - foreach (var width in widths) - { - n += width; - } - int val = 0; - int narrowMask = 0; - for (int bar = 0; bar < elements - 1; bar++) - { - int elmWidth; - for (elmWidth = 1, narrowMask |= 1 << bar; - elmWidth < widths[bar]; - elmWidth++, narrowMask &= ~(1 << bar)) - { - int subVal = combins(n - elmWidth - 1, elements - bar - 2); - if (noNarrow && (narrowMask == 0) && - (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)) - { - subVal -= combins(n - elmWidth - (elements - bar), - elements - bar - 2); - } - if (elements - bar - 1 > 1) - { - int lessVal = 0; - for (int mxwElement = n - elmWidth - (elements - bar - 2); - mxwElement > maxWidth; mxwElement--) - { - lessVal += combins(n - elmWidth - mxwElement - 1, - elements - bar - 3); - } - subVal -= lessVal * (elements - 1 - bar); - } - else if (n - elmWidth > maxWidth) - { - subVal--; - } - val += subVal; - } - n -= elmWidth; - } - return val; - } - - private static int combins(int n, int r) - { - int maxDenom; - int minDenom; - if (n - r > r) - { - minDenom = r; - maxDenom = n - r; - } - else - { - minDenom = n - r; - maxDenom = r; - } - int val = 1; - int j = 1; - for (int i = n; i > maxDenom; i--) - { - val *= i; - if (j <= minDenom) - { - val /= j; - j++; - } - } - while (j <= minDenom) - { - val /= j; - j++; - } - return val; - } - /* - internal static int[] elements(int[] eDist, int N, int K) - { - int[] widths = new int[eDist.Length + 2]; - int twoK = K << 1; - widths[0] = 1; - int i; - int minEven = 10; - int barSum = 1; - for (i = 1; i < twoK - 2; i += 2) - { - widths[i] = eDist[i - 1] - widths[i - 1]; - widths[i + 1] = eDist[i] - widths[i]; - barSum += widths[i] + widths[i + 1]; - if (widths[i] < minEven) - { - minEven = widths[i]; - } - } - widths[twoK - 1] = N - barSum; - if (widths[twoK - 1] < minEven) - { - minEven = widths[twoK - 1]; - } - if (minEven > 1) - { - for (i = 0; i < twoK; i += 2) - { - widths[i] += minEven - 1; - widths[i + 1] -= minEven - 1; - } - } - return widths; - } - */ - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/rss/expanded/BitArrayBuilder.cs b/zxing.core/xx/oned/rss/expanded/BitArrayBuilder.cs deleted file mode 100644 index 4ef1a46..0000000 --- a/zxing.core/xx/oned/rss/expanded/BitArrayBuilder.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -using System.Collections.Generic; -using ZXing.Common; - -namespace ZXing.OneD.RSS.Expanded -{ - /// - /// Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - /// Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - /// - static class BitArrayBuilder - { - internal static BitArray buildBitArray(List pairs) - { - int charNumber = (pairs.Count << 1) - 1; - if (pairs[pairs.Count - 1].RightChar == null) - { - charNumber -= 1; - } - - int size = 12 * charNumber; - - BitArray binary = new BitArray(size); - int accPos = 0; - - ExpandedPair firstPair = pairs[0]; - int firstValue = firstPair.RightChar.Value; - for (int i = 11; i >= 0; --i) - { - if ((firstValue & (1 << i)) != 0) - { - binary[accPos] = true; - } - accPos++; - } - - for (int i = 1; i < pairs.Count; ++i) - { - ExpandedPair currentPair = pairs[i]; - - int leftValue = currentPair.LeftChar.Value; - for (int j = 11; j >= 0; --j) - { - if ((leftValue & (1 << j)) != 0) - { - binary[accPos] = true; - } - accPos++; - } - - if (currentPair.RightChar != null) - { - int rightValue = currentPair.RightChar.Value; - for (int j = 11; j >= 0; --j) - { - if ((rightValue & (1 << j)) != 0) - { - binary[accPos] = true; - } - accPos++; - } - } - } - return binary; - } - } -} diff --git a/zxing.core/xx/oned/rss/expanded/ExpandedPair.cs b/zxing.core/xx/oned/rss/expanded/ExpandedPair.cs deleted file mode 100644 index 6082230..0000000 --- a/zxing.core/xx/oned/rss/expanded/ExpandedPair.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -using System; - -namespace ZXing.OneD.RSS.Expanded -{ - /// - /// Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - /// - internal sealed class ExpandedPair - { - internal bool MayBeLast { get; private set; } - internal DataCharacter LeftChar { get; private set; } - internal DataCharacter RightChar { get; private set; } - internal FinderPattern FinderPattern { get; private set; } - - internal ExpandedPair(DataCharacter leftChar, - DataCharacter rightChar, - FinderPattern finderPattern, - bool mayBeLast) - { - LeftChar = leftChar; - RightChar = rightChar; - FinderPattern = finderPattern; - MayBeLast = mayBeLast; - } - - public bool MustBeLast - { - get { return RightChar == null; } - } - - override public String ToString() - { - return - "[ " + LeftChar + " , " + RightChar + " : " + - (FinderPattern == null ? "null" : FinderPattern.Value.ToString()) + " ]"; - } - - override public bool Equals(Object o) - { - if (!(o is ExpandedPair)) - { - return false; - } - ExpandedPair that = (ExpandedPair)o; - return - EqualsOrNull(LeftChar, that.LeftChar) && - EqualsOrNull(RightChar, that.RightChar) && - EqualsOrNull(FinderPattern, that.FinderPattern); - } - - private static bool EqualsOrNull(Object o1, Object o2) - { - return o1 == null ? o2 == null : o1.Equals(o2); - } - - override public int GetHashCode() - { - return hashNotNull(LeftChar) ^ hashNotNull(RightChar) ^ hashNotNull(FinderPattern); - } - - private static int hashNotNull(Object o) - { - return o == null ? 0 : o.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/rss/expanded/ExpandedRow.cs b/zxing.core/xx/oned/rss/expanded/ExpandedRow.cs deleted file mode 100644 index 9843af1..0000000 --- a/zxing.core/xx/oned/rss/expanded/ExpandedRow.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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; - -namespace ZXing.OneD.RSS.Expanded -{ - /// - /// One row of an RSS Expanded Stacked symbol, consisting of 1+ expanded pairs. - /// - internal sealed class ExpandedRow - { - internal ExpandedRow(List pairs, int rowNumber, bool wasReversed) - { - Pairs = new List(pairs); - RowNumber = rowNumber; - IsReversed = wasReversed; - } - - internal List Pairs { get; private set; } - - internal int RowNumber { get; private set; } - - /// - /// Did this row of the image have to be reversed (mirrored) to recognize the pairs? - /// - internal bool IsReversed { get; private set; } - - internal bool IsEquivalent(List otherPairs) - { - return Pairs.Equals(otherPairs); - } - - override public String ToString() - { - return "{ " + Pairs + " }"; - } - - /// - /// Two rows are equal if they contain the same pairs in the same order. - /// - override public bool Equals(Object o) - { - if (!(o is ExpandedRow)) - { - return false; - } - ExpandedRow that = (ExpandedRow)o; - return Pairs.Equals(that.Pairs) && IsReversed == that.IsReversed; - } - - override public int GetHashCode() - { - return Pairs.GetHashCode() ^ IsReversed.GetHashCode(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/oned/rss/expanded/RSSExpandedReader.cs b/zxing.core/xx/oned/rss/expanded/RSSExpandedReader.cs deleted file mode 100644 index 02507ca..0000000 --- a/zxing.core/xx/oned/rss/expanded/RSSExpandedReader.cs +++ /dev/null @@ -1,924 +0,0 @@ -/* - * 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. - */ - -/* - * These authors would like to acknowledge the Spanish Ministry of Industry, - * Tourism and Trade, for the support in the project TSI020301-2008-2 - * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled - * Mobile Dynamic Environments", led by Treelogic - * ( http://www.treelogic.com/ ): - * - * http://www.piramidepse.com/ - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.OneD.RSS.Expanded.Decoders; - -namespace ZXing.OneD.RSS.Expanded -{ - /// - /// Pablo Orduña, University of Deusto (pablo.orduna@deusto.es) - /// Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es) - /// - public sealed class RSSExpandedReader : AbstractRSSReader - { - private static readonly int[] SYMBOL_WIDEST = { 7, 5, 4, 3, 1 }; - private static readonly int[] EVEN_TOTAL_SUBSET = { 4, 20, 52, 104, 204 }; - private static readonly int[] GSUM = { 0, 348, 1388, 2948, 3988 }; - - private static readonly int[][] FINDER_PATTERNS = { - new[] {1, 8, 4, 1}, // A - new[] {3, 6, 4, 1}, // B - new[] {3, 4, 6, 1}, // C - new[] {3, 2, 8, 1}, // D - new[] {2, 6, 5, 1}, // E - new[] {2, 2, 9, 1} // F - }; - - private static readonly int[][] WEIGHTS = { - new[] {1, 3, 9, 27, 81, 32, 96, 77}, - new[] {20, 60, 180, 118, 143, 7, 21, 63}, - new[] {189, 145, 13, 39, 117, 140, 209, 205}, - new[] {193, 157, 49, 147, 19, 57, 171, 91}, - new[] {62, 186, 136, 197, 169, 85, 44, 132}, - new[] {185, 133, 188, 142, 4, 12, 36, 108}, - new[] {113, 128, 173, 97, 80, 29, 87, 50}, - new[] {150, 28, 84, 41, 123, 158, 52, 156}, - new[] {46, 138, 203, 187, 139, 206, 196, 166}, - new[] {76, 17, 51, 153, 37, 111, 122, 155}, - new[] {43, 129, 176, 106, 107, 110, 119, 146}, - new[] {16, 48, 144, 10, 30, 90, 59, 177}, - new[] {109, 116, 137, 200, 178, 112, 125, 164}, - new[] {70, 210, 208, 202, 184, 130, 179, 115}, - new[] {134, 191, 151, 31, 93, 68, 204, 190}, - new[] {148, 22, 66, 198, 172, 94, 71, 2}, - new[] {6, 18, 54, 162, 64, 192, 154, 40}, - new[] {120, 149, 25, 75, 14, 42, 126, 167}, - new[] {79, 26, 78, 23, 69, 207, 199, 175}, - new[] {103, 98, 83, 38, 114, 131, 182, 124}, - new[] {161, 61, 183, 127, 170, 88, 53, 159}, - new[] {55, 165, 73, 8, 24, 72, 5, 15}, - new[] {45, 135, 194, 160, 58, 174, 100, 89} - }; - private const int FINDER_PAT_A = 0; - private const int FINDER_PAT_B = 1; - private const int FINDER_PAT_C = 2; - private const int FINDER_PAT_D = 3; - private const int FINDER_PAT_E = 4; - private const int FINDER_PAT_F = 5; - - private static readonly int[][] FINDER_PATTERN_SEQUENCES = { - new[] { FINDER_PAT_A, FINDER_PAT_A }, - new[] { FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B }, - new[] { FINDER_PAT_A, FINDER_PAT_C, FINDER_PAT_B, FINDER_PAT_D }, - new[] { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_C }, - new[] { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_F }, - new[] { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F }, - new[] { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D }, - new[] { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E }, - new[] { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F }, - new[] { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F }, - }; - - // private static readonly int LONGEST_SEQUENCE_SIZE = FINDER_PATTERN_SEQUENCES[FINDER_PATTERN_SEQUENCES.Length - 1].Length; - - private const int MAX_PAIRS = 11; - - private readonly List pairs = new List(MAX_PAIRS); - private readonly List rows = new List(); - private readonly int[] startEnd = new int[2]; - //private readonly int[] currentSequence = new int[LONGEST_SEQUENCE_SIZE]; - private bool startFromEven = false; - - internal List Pairs { get { return pairs; } } - - /// - ///

Attempts to decode a one-dimensional barcode format given a single row of - /// an image.

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

This class contains the methods for decoding the PDF417 codewords.

- /// - /// SITA Lab (kevin.osullivan@sita.aero) - ///
- internal static class DecodedBitStreamParser - { - private enum Mode - { - ALPHA, - LOWER, - MIXED, - PUNCT, - ALPHA_SHIFT, - PUNCT_SHIFT - } - - private const int TEXT_COMPACTION_MODE_LATCH = 900; - private const int BYTE_COMPACTION_MODE_LATCH = 901; - private const int NUMERIC_COMPACTION_MODE_LATCH = 902; - private const int BYTE_COMPACTION_MODE_LATCH_6 = 924; - private const int ECI_USER_DEFINED = 925; - private const int ECI_GENERAL_PURPOSE = 926; - private const int ECI_CHARSET = 927; - private const int BEGIN_MACRO_PDF417_CONTROL_BLOCK = 928; - private const int BEGIN_MACRO_PDF417_OPTIONAL_FIELD = 923; - private const int MACRO_PDF417_TERMINATOR = 922; - private const int MODE_SHIFT_TO_BYTE_COMPACTION_MODE = 913; - private const int MAX_NUMERIC_CODEWORDS = 15; - - private const int PL = 25; - private const int LL = 27; - private const int AS = 27; - private const int ML = 28; - private const int AL = 28; - private const int PS = 29; - private const int PAL = 29; - - private static readonly char[] PUNCT_CHARS = { - ';', '<', '>', '@', '[', '\\', ']', '_', '`', '~', '!', - '\r', '\t', ',', ':', '\n', '-', '.', '$', '/', '"', '|', '*', - '(', ')', '?', '{', '}', '\'' - }; - - private static readonly char[] MIXED_CHARS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '&', - '\r', '\t', ',', ':', '#', '-', '.', '$', '/', '+', '%', '*', - '=', '^' - }; - - /// - /// Table containing values for the exponent of 900. - /// This is used in the numeric compaction decode algorithm. - /// - private static readonly BigInteger[] EXP900; - static DecodedBitStreamParser() - { - EXP900 = new BigInteger[16]; - EXP900[0] = BigInteger.One; - BigInteger nineHundred = new BigInteger(900); - EXP900[1] = nineHundred; - for (int i = 2; i < EXP900.Length; i++) - { - EXP900[i] = BigInteger.Multiply(EXP900[i - 1], nineHundred); - } - } - private const int NUMBER_OF_SEQUENCE_CODEWORDS = 2; - - internal static DecoderResult decode(int[] codewords, String ecLevel) - { - var result = new StringBuilder(codewords.Length * 2); - // Get compaction mode - int codeIndex = 1; - int code = codewords[codeIndex++]; - var resultMetadata = new PDF417ResultMetadata(); - Encoding encoding = null; - - while (codeIndex < codewords[0]) - { - switch (code) - { - case TEXT_COMPACTION_MODE_LATCH: - codeIndex = textCompaction(codewords, codeIndex, result); - break; - case BYTE_COMPACTION_MODE_LATCH: - case BYTE_COMPACTION_MODE_LATCH_6: - codeIndex = byteCompaction(code, codewords, encoding ?? (encoding = getEncoding(PDF417HighLevelEncoder.DEFAULT_ENCODING_NAME)), codeIndex, result); - break; - case MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - result.Append((char)codewords[codeIndex++]); - break; - case NUMERIC_COMPACTION_MODE_LATCH: - codeIndex = numericCompaction(codewords, codeIndex, result); - break; - case ECI_CHARSET: - var charsetECI = CharacterSetECI.getCharacterSetECIByValue(codewords[codeIndex++]); - encoding = getEncoding(charsetECI.EncodingName); - break; - case ECI_GENERAL_PURPOSE: - // Can't do anything with generic ECI; skip its 2 characters - codeIndex += 2; - break; - case ECI_USER_DEFINED: - // Can't do anything with user ECI; skip its 1 character - codeIndex++; - break; - case BEGIN_MACRO_PDF417_CONTROL_BLOCK: - codeIndex = decodeMacroBlock(codewords, codeIndex, resultMetadata); - break; - case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: - case MACRO_PDF417_TERMINATOR: - // Should not see these outside a macro block - return null; - default: - // Default to text compaction. During testing numerous barcodes - // appeared to be missing the starting mode. In these cases defaulting - // to text compaction seems to work. - codeIndex--; - codeIndex = textCompaction(codewords, codeIndex, result); - break; - } - if (codeIndex < 0) - return null; - if (codeIndex < codewords.Length) - { - code = codewords[codeIndex++]; - } - else - { - return null; - } - } - - if (result.Length == 0) - { - return null; - } - - var decoderResult = new DecoderResult(null, result.ToString(), null, ecLevel); - decoderResult.Other = resultMetadata; - return decoderResult; - } - - private static Encoding getEncoding(string encodingName) - { - Encoding encoding = null; - - try - { - encoding = Encoding.GetEncoding(encodingName); - } -#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 - encoding = Encoding.GetEncoding("UTF-8"); - } - catch (Exception) - { - } - } -#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 (encodingName == "ISO-8859-1") - { - encoding = Encoding.GetEncoding(1252); - } - else - { - encoding = Encoding.GetEncoding("UTF-8"); - } - } - catch (Exception) - { - } - } -#endif - catch (Exception) - { - return null; - } - - return encoding; - } - - private static int decodeMacroBlock(int[] codewords, int codeIndex, PDF417ResultMetadata resultMetadata) - { - if (codeIndex + NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) - { - // we must have at least two bytes left for the segment index - return -1; - } - int[] segmentIndexArray = new int[NUMBER_OF_SEQUENCE_CODEWORDS]; - for (int i = 0; i < NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) - { - segmentIndexArray[i] = codewords[codeIndex]; - } - String s = decodeBase900toBase10(segmentIndexArray, NUMBER_OF_SEQUENCE_CODEWORDS); - if (s == null) - return -1; - resultMetadata.SegmentIndex = Int32.Parse(s); - - StringBuilder fileId = new StringBuilder(); - codeIndex = textCompaction(codewords, codeIndex, fileId); - resultMetadata.FileId = fileId.ToString(); - - if (codewords[codeIndex] == BEGIN_MACRO_PDF417_OPTIONAL_FIELD) - { - codeIndex++; - int[] additionalOptionCodeWords = new int[codewords[0] - codeIndex]; - int additionalOptionCodeWordsIndex = 0; - - bool end = false; - while ((codeIndex < codewords[0]) && !end) - { - int code = codewords[codeIndex++]; - if (code < TEXT_COMPACTION_MODE_LATCH) - { - additionalOptionCodeWords[additionalOptionCodeWordsIndex++] = code; - } - else - { - switch (code) - { - case MACRO_PDF417_TERMINATOR: - resultMetadata.IsLastSegment = true; - codeIndex++; - end = true; - break; - default: - return -1; - } - } - } - resultMetadata.OptionalData = new int[additionalOptionCodeWordsIndex]; - Array.Copy(additionalOptionCodeWords, resultMetadata.OptionalData, additionalOptionCodeWordsIndex); - } - else if (codewords[codeIndex] == MACRO_PDF417_TERMINATOR) - { - resultMetadata.IsLastSegment = true; - codeIndex++; - } - - return codeIndex; - } - - /// - /// Text Compaction mode (see 5.4.1.5) permits all printable ASCII characters to be - /// encoded, i.e. values 32 - 126 inclusive in accordance with ISO/IEC 646 (IRV), as - /// well as selected control characters. - /// - /// The array of codewords (data + error) - /// The current index into the codeword array. - /// The decoded data is appended to the result. - /// The next index into the codeword array. - /// - private static int textCompaction(int[] codewords, int codeIndex, StringBuilder result) - { - // 2 character per codeword - int[] textCompactionData = new int[(codewords[0] - codeIndex) << 1]; - // Used to hold the byte compaction value if there is a mode shift - int[] byteCompactionData = new int[(codewords[0] - codeIndex) << 1]; - - int index = 0; - bool end = false; - while ((codeIndex < codewords[0]) && !end) - { - int code = codewords[codeIndex++]; - if (code < TEXT_COMPACTION_MODE_LATCH) - { - textCompactionData[index] = code / 30; - textCompactionData[index + 1] = code % 30; - index += 2; - } - else - { - switch (code) - { - case TEXT_COMPACTION_MODE_LATCH: - // reinitialize text compaction mode to alpha sub mode - textCompactionData[index++] = TEXT_COMPACTION_MODE_LATCH; - break; - case BYTE_COMPACTION_MODE_LATCH: - case BYTE_COMPACTION_MODE_LATCH_6: - case NUMERIC_COMPACTION_MODE_LATCH: - case BEGIN_MACRO_PDF417_CONTROL_BLOCK: - case BEGIN_MACRO_PDF417_OPTIONAL_FIELD: - case MACRO_PDF417_TERMINATOR: - codeIndex--; - end = true; - break; - case MODE_SHIFT_TO_BYTE_COMPACTION_MODE: - // The Mode Shift codeword 913 shall cause a temporary - // switch from Text Compaction mode to Byte Compaction mode. - // This switch shall be in effect for only the next codeword, - // after which the mode shall revert to the prevailing sub-mode - // of the Text Compaction mode. Codeword 913 is only available - // in Text Compaction mode; its use is described in 5.4.2.4. - textCompactionData[index] = MODE_SHIFT_TO_BYTE_COMPACTION_MODE; - code = codewords[codeIndex++]; - byteCompactionData[index] = code; - index++; - break; - } - } - } - decodeTextCompaction(textCompactionData, byteCompactionData, index, result); - return codeIndex; - } - - /// - /// The Text Compaction mode includes all the printable ASCII characters - /// (i.e. values from 32 to 126) and three ASCII control characters: HT or tab - /// (ASCII value 9), LF or line feed (ASCII value 10), and CR or carriage - /// return (ASCII value 13). The Text Compaction mode also includes various latch - /// and shift characters which are used exclusively within the mode. The Text - /// Compaction mode encodes up to 2 characters per codeword. The compaction rules - /// for converting data into PDF417 codewords are defined in 5.4.2.2. The sub-mode - /// switches are defined in 5.4.2.3. - /// - /// The text compaction data. - /// The byte compaction data if there - /// was a mode shift. - /// The size of the text compaction and byte compaction data. - /// The decoded data is appended to the result. - /// - private static void decodeTextCompaction(int[] textCompactionData, - int[] byteCompactionData, - int length, - StringBuilder result) - { - // Beginning from an initial state of the Alpha sub-mode - // The default compaction mode for PDF417 in effect at the start of each symbol shall always be Text - // Compaction mode Alpha sub-mode (uppercase alphabetic). A latch codeword from another mode to the Text - // Compaction mode shall always switch to the Text Compaction Alpha sub-mode. - Mode subMode = Mode.ALPHA; - Mode priorToShiftMode = Mode.ALPHA; - int i = 0; - while (i < length) - { - int subModeCh = textCompactionData[i]; - char? ch = null; - switch (subMode) - { - case Mode.ALPHA: - // Alpha (uppercase alphabetic) - if (subModeCh < 26) - { - // Upper case Alpha Character - ch = (char)('A' + subModeCh); - } - else - { - if (subModeCh == 26) - { - ch = ' '; - } - else if (subModeCh == LL) - { - subMode = Mode.LOWER; - } - else if (subModeCh == ML) - { - subMode = Mode.MIXED; - } - else if (subModeCh == PS) - { - // Shift to punctuation - priorToShiftMode = subMode; - subMode = Mode.PUNCT_SHIFT; - } - else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) - { - // TODO Does this need to use the current character encoding? See other occurrences below - result.Append((char)byteCompactionData[i]); - } - else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) - { - subMode = Mode.ALPHA; - } - } - break; - - case Mode.LOWER: - // Lower (lowercase alphabetic) - if (subModeCh < 26) - { - ch = (char)('a' + subModeCh); - } - else - { - if (subModeCh == 26) - { - ch = ' '; - } - else if (subModeCh == AS) - { - // Shift to alpha - priorToShiftMode = subMode; - subMode = Mode.ALPHA_SHIFT; - } - else if (subModeCh == ML) - { - subMode = Mode.MIXED; - } - else if (subModeCh == PS) - { - // Shift to punctuation - priorToShiftMode = subMode; - subMode = Mode.PUNCT_SHIFT; - } - else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) - { - result.Append((char)byteCompactionData[i]); - } - else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) - { - subMode = Mode.ALPHA; - } - } - break; - - case Mode.MIXED: - // Mixed (numeric and some punctuation) - if (subModeCh < PL) - { - ch = MIXED_CHARS[subModeCh]; - } - else - { - if (subModeCh == PL) - { - subMode = Mode.PUNCT; - } - else if (subModeCh == 26) - { - ch = ' '; - } - else if (subModeCh == LL) - { - subMode = Mode.LOWER; - } - else if (subModeCh == AL) - { - subMode = Mode.ALPHA; - } - else if (subModeCh == PS) - { - // Shift to punctuation - priorToShiftMode = subMode; - subMode = Mode.PUNCT_SHIFT; - } - else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) - { - result.Append((char)byteCompactionData[i]); - } - else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) - { - subMode = Mode.ALPHA; - } - } - break; - - case Mode.PUNCT: - // Punctuation - if (subModeCh < PAL) - { - ch = PUNCT_CHARS[subModeCh]; - } - else - { - if (subModeCh == PAL) - { - subMode = Mode.ALPHA; - } - else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) - { - result.Append((char)byteCompactionData[i]); - } - else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) - { - subMode = Mode.ALPHA; - } - } - break; - - case Mode.ALPHA_SHIFT: - // Restore sub-mode - subMode = priorToShiftMode; - if (subModeCh < 26) - { - ch = (char)('A' + subModeCh); - } - else - { - if (subModeCh == 26) - { - ch = ' '; - } - else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) - { - subMode = Mode.ALPHA; - } - } - break; - - case Mode.PUNCT_SHIFT: - // Restore sub-mode - subMode = priorToShiftMode; - if (subModeCh < PAL) - { - ch = PUNCT_CHARS[subModeCh]; - } - else - { - if (subModeCh == PAL) - { - subMode = Mode.ALPHA; - } - else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) - { - // PS before Shift-to-Byte is used as a padding character, - // see 5.4.2.4 of the specification - result.Append((char)byteCompactionData[i]); - } - else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) - { - subMode = Mode.ALPHA; - } - } - break; - } - if (ch != null) - { - // Append decoded character to result - result.Append(ch.Value); - } - i++; - } - } - - /// - /// Byte Compaction mode (see 5.4.3) permits all 256 possible 8-bit byte values to be encoded. - /// This includes all ASCII characters value 0 to 127 inclusive and provides for international - /// character set support. - /// - /// The byte compaction mode i.e. 901 or 924 - /// The array of codewords (data + error) - /// Currently active character encoding - /// The current index into the codeword array. - /// The decoded data is appended to the result. - /// The next index into the codeword array. - /// - private static int byteCompaction(int mode, int[] codewords, Encoding encoding, int codeIndex, StringBuilder result) - { - var decodedBytes = new System.IO.MemoryStream(); - if (mode == BYTE_COMPACTION_MODE_LATCH) - { - // Total number of Byte Compaction characters to be encoded - // is not a multiple of 6 - int count = 0; - long value = 0; - int[] byteCompactedCodewords = new int[6]; - bool end = false; - int nextCode = codewords[codeIndex++]; - while ((codeIndex < codewords[0]) && !end) - { - byteCompactedCodewords[count++] = nextCode; - // Base 900 - value = 900 * value + nextCode; - nextCode = codewords[codeIndex++]; - // perhaps it should be ok to check only nextCode >= TEXT_COMPACTION_MODE_LATCH - if (nextCode == TEXT_COMPACTION_MODE_LATCH || - nextCode == BYTE_COMPACTION_MODE_LATCH || - nextCode == NUMERIC_COMPACTION_MODE_LATCH || - nextCode == BYTE_COMPACTION_MODE_LATCH_6 || - nextCode == BEGIN_MACRO_PDF417_CONTROL_BLOCK || - nextCode == BEGIN_MACRO_PDF417_OPTIONAL_FIELD || - nextCode == MACRO_PDF417_TERMINATOR) - { - codeIndex--; - end = true; - } - else - { - if ((count%5 == 0) && (count > 0)) - { - // Decode every 5 codewords - // Convert to Base 256 - for (int j = 0; j < 6; ++j) - { - decodedBytes.WriteByte((byte)(value >> (8 * (5 - j)))); - } - value = 0; - count = 0; - } - } - } - - // if the end of all codewords is reached the last codeword needs to be added - if (codeIndex == codewords[0] && nextCode < TEXT_COMPACTION_MODE_LATCH) - byteCompactedCodewords[count++] = nextCode; - - // If Byte Compaction mode is invoked with codeword 901, - // the last group of codewords is interpreted directly - // as one byte per codeword, without compaction. - for (int i = 0; i < count; i++) - { - decodedBytes.WriteByte((byte)byteCompactedCodewords[i]); - } - } - else if (mode == BYTE_COMPACTION_MODE_LATCH_6) - { - // Total number of Byte Compaction characters to be encoded - // is an integer multiple of 6 - int count = 0; - long value = 0; - bool end = false; - while (codeIndex < codewords[0] && !end) - { - int code = codewords[codeIndex++]; - if (code < TEXT_COMPACTION_MODE_LATCH) - { - count++; - // Base 900 - value = 900 * value + code; - } - else - { - if (code == TEXT_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH || - code == NUMERIC_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH_6 || - code == BEGIN_MACRO_PDF417_CONTROL_BLOCK || - code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD || - code == MACRO_PDF417_TERMINATOR) - { - codeIndex--; - end = true; - } - } - if ((count % 5 == 0) && (count > 0)) - { - // Decode every 5 codewords - // Convert to Base 256 - for (int j = 0; j < 6; ++j) - { - decodedBytes.WriteByte((byte)(value >> (8 * (5 - j)))); - } - value = 0; - count = 0; - } - } - } - var bytes = decodedBytes.ToArray(); - result.Append(encoding.GetString(bytes, 0, bytes.Length)); - return codeIndex; - } - - /// - /// Numeric Compaction mode (see 5.4.4) permits efficient encoding of numeric data strings. - /// - /// The array of codewords (data + error) - /// The current index into the codeword array. - /// The decoded data is appended to the result. - /// The next index into the codeword array. - /// - private static int numericCompaction(int[] codewords, int codeIndex, StringBuilder result) - { - int count = 0; - bool end = false; - - int[] numericCodewords = new int[MAX_NUMERIC_CODEWORDS]; - - while (codeIndex < codewords[0] && !end) - { - int code = codewords[codeIndex++]; - if (codeIndex == codewords[0]) - { - end = true; - } - if (code < TEXT_COMPACTION_MODE_LATCH) - { - numericCodewords[count] = code; - count++; - } - else - { - if (code == TEXT_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH || - code == BYTE_COMPACTION_MODE_LATCH_6 || - code == BEGIN_MACRO_PDF417_CONTROL_BLOCK || - code == BEGIN_MACRO_PDF417_OPTIONAL_FIELD || - code == MACRO_PDF417_TERMINATOR) - { - codeIndex--; - end = true; - } - } - if (count % MAX_NUMERIC_CODEWORDS == 0 || - code == NUMERIC_COMPACTION_MODE_LATCH || - end) - { - // Re-invoking Numeric Compaction mode (by using codeword 902 - // while in Numeric Compaction mode) serves to terminate the - // current Numeric Compaction mode grouping as described in 5.4.4.2, - // and then to start a new one grouping. - if (count > 0) - { - String s = decodeBase900toBase10(numericCodewords, count); - if (s == null) - return -1; - result.Append(s); - count = 0; - } - } - } - return codeIndex; - } - - /// - /// Convert a list of Numeric Compacted codewords from Base 900 to Base 10. - /// EXAMPLE - /// Encode the fifteen digit numeric string 000213298174000 - /// Prefix the numeric string with a 1 and set the initial value of - /// t = 1 000 213 298 174 000 - /// Calculate codeword 0 - /// d0 = 1 000 213 298 174 000 mod 900 = 200 - /// - /// t = 1 000 213 298 174 000 div 900 = 1 111 348 109 082 - /// Calculate codeword 1 - /// d1 = 1 111 348 109 082 mod 900 = 282 - /// - /// t = 1 111 348 109 082 div 900 = 1 234 831 232 - /// Calculate codeword 2 - /// d2 = 1 234 831 232 mod 900 = 632 - /// - /// t = 1 234 831 232 div 900 = 1 372 034 - /// Calculate codeword 3 - /// d3 = 1 372 034 mod 900 = 434 - /// - /// t = 1 372 034 div 900 = 1 524 - /// Calculate codeword 4 - /// d4 = 1 524 mod 900 = 624 - /// - /// t = 1 524 div 900 = 1 - /// Calculate codeword 5 - /// d5 = 1 mod 900 = 1 - /// t = 1 div 900 = 0 - /// Codeword sequence is: 1, 624, 434, 632, 282, 200 - /// - /// Decode the above codewords involves - /// 1 x 900 power of 5 + 624 x 900 power of 4 + 434 x 900 power of 3 + - /// 632 x 900 power of 2 + 282 x 900 power of 1 + 200 x 900 power of 0 = 1000213298174000 - /// - /// Remove leading 1 => Result is 000213298174000 - /// The array of codewords - /// The number of codewords - /// The decoded string representing the Numeric data. - /// - private static String decodeBase900toBase10(int[] codewords, int count) - { - BigInteger result = BigInteger.Zero; - for (int i = 0; i < count; i++) - { - result = BigInteger.Add(result, BigInteger.Multiply(EXP900[count - i - 1], new BigInteger(codewords[i]))); - } - String resultString = result.ToString(); - if (resultString[0] != '1') - { - return null; - } - return resultString.Substring(1); - } - } -} diff --git a/zxing.core/xx/pdf417/decoder/DetectionResult.cs b/zxing.core/xx/pdf417/decoder/DetectionResult.cs deleted file mode 100644 index 207a316..0000000 --- a/zxing.core/xx/pdf417/decoder/DetectionResult.cs +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2013 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.Globalization; -using System.Text; - -namespace ZXing.PDF417.Internal -{ - /// - /// - /// - /// Guenther Grau - public class DetectionResult - { - private const int ADJUST_ROW_NUMBER_SKIP = 2; - - public BarcodeMetadata Metadata { get; private set; } - public DetectionResultColumn[] DetectionResultColumns { get; set; } - public BoundingBox Box { get; set; } - public int ColumnCount { get; private set; } - - public int RowCount - { - get { return Metadata.RowCount; } - } - - public int ErrorCorrectionLevel - { - get { return Metadata.ErrorCorrectionLevel; } - } - - public DetectionResult(BarcodeMetadata metadata, BoundingBox box) - { - Metadata = metadata; - Box = box; - ColumnCount = metadata.ColumnCount; - DetectionResultColumns = new DetectionResultColumn[ColumnCount + 2]; - } - - /// - /// Returns the DetectionResult Columns. This does a fair bit of calculation, so call it sparingly. - /// - /// The detection result columns. - public DetectionResultColumn[] getDetectionResultColumns() - { - adjustIndicatorColumnRowNumbers(DetectionResultColumns[0]); - adjustIndicatorColumnRowNumbers(DetectionResultColumns[ColumnCount + 1]); - int unadjustedCodewordCount = PDF417Common.MAX_CODEWORDS_IN_BARCODE; - int previousUnadjustedCount; - do - { - previousUnadjustedCount = unadjustedCodewordCount; - unadjustedCodewordCount = adjustRowNumbers(); - } while (unadjustedCodewordCount > 0 && unadjustedCodewordCount < previousUnadjustedCount); - return DetectionResultColumns; - } - - /// - /// Adjusts the indicator column row numbers. - /// - /// Detection result column. - private void adjustIndicatorColumnRowNumbers(DetectionResultColumn detectionResultColumn) - { - if (detectionResultColumn != null) - { - ((DetectionResultRowIndicatorColumn) detectionResultColumn) - .adjustCompleteIndicatorColumnRowNumbers(Metadata); - } - } - - /// - /// return number of codewords which don't have a valid row number. Note that the count is not accurate as codewords . - /// will be counted several times. It just serves as an indicator to see when we can stop adjusting row numbers - /// - /// The row numbers. - private int adjustRowNumbers() - { - // TODO ensure that no detected codewords with unknown row number are left - // we should be able to estimate the row height and use it as a hint for the row number - // we should also fill the rows top to bottom and bottom to top - int unadjustedCount = adjustRowNumbersByRow(); - if (unadjustedCount == 0) - { - return 0; - } - for (int barcodeColumn = 1; barcodeColumn < ColumnCount + 1; barcodeColumn++) - { - Codeword[] codewords = DetectionResultColumns[barcodeColumn].Codewords; - for (int codewordsRow = 0; codewordsRow < codewords.Length; codewordsRow++) - { - if (codewords[codewordsRow] == null) - { - continue; - } - if (!codewords[codewordsRow].HasValidRowNumber) - { - adjustRowNumbers(barcodeColumn, codewordsRow, codewords); - } - } - } - return unadjustedCount; - } - - /// - /// Adjusts the row numbers by row. - /// - /// The row numbers by row. - private int adjustRowNumbersByRow() - { - adjustRowNumbersFromBothRI(); // RI = RowIndicators - // TODO we should only do full row adjustments if row numbers of left and right row indicator column match. - // Maybe it's even better to calculated the height (in codeword rows) and divide it by the number of barcode - // rows. This, together with the LRI and RRI row numbers should allow us to get a good estimate where a row - // number starts and ends. - int unadjustedCount = adjustRowNumbersFromLRI(); - return unadjustedCount + adjustRowNumbersFromRRI(); - } - - /// - /// Adjusts the row numbers from both Row Indicators - /// - /// zero - private void adjustRowNumbersFromBothRI() - { - if (DetectionResultColumns[0] == null || DetectionResultColumns[ColumnCount + 1] == null) - { - return; - } - Codeword[] LRIcodewords = DetectionResultColumns[0].Codewords; - Codeword[] RRIcodewords = DetectionResultColumns[ColumnCount + 1].Codewords; - for (int codewordsRow = 0; codewordsRow < LRIcodewords.Length; codewordsRow++) - { - if (LRIcodewords[codewordsRow] != null && - RRIcodewords[codewordsRow] != null && - LRIcodewords[codewordsRow].RowNumber == RRIcodewords[codewordsRow].RowNumber) - { - for (int barcodeColumn = 1; barcodeColumn <= ColumnCount; barcodeColumn++) - { - Codeword codeword = DetectionResultColumns[barcodeColumn].Codewords[codewordsRow]; - if (codeword == null) - { - continue; - } - codeword.RowNumber = LRIcodewords[codewordsRow].RowNumber; - if (!codeword.HasValidRowNumber) - { - // LOG.info("Removing codeword with invalid row number, cw[" + codewordsRow + "][" + barcodeColumn + "]"); - DetectionResultColumns[barcodeColumn].Codewords[codewordsRow] = null; - } - } - } - } - } - - /// - /// Adjusts the row numbers from Right Row Indicator. - /// - /// The unadjusted row count. - private int adjustRowNumbersFromRRI() - { - if (DetectionResultColumns[ColumnCount + 1] == null) - { - return 0; - } - int unadjustedCount = 0; - Codeword[] codewords = DetectionResultColumns[ColumnCount + 1].Codewords; - for (int codewordsRow = 0; codewordsRow < codewords.Length; codewordsRow++) - { - if (codewords[codewordsRow] == null) - { - continue; - } - int rowIndicatorRowNumber = codewords[codewordsRow].RowNumber; - int invalidRowCounts = 0; - for (int barcodeColumn = ColumnCount + 1; barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP; barcodeColumn--) - { - Codeword codeword = DetectionResultColumns[barcodeColumn].Codewords[codewordsRow]; - if (codeword != null) - { - invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword); - if (!codeword.HasValidRowNumber) - { - unadjustedCount++; - } - } - } - } - return unadjustedCount; - } - - /// - /// Adjusts the row numbers from Left Row Indicator. - /// - /// Unadjusted row Count. - private int adjustRowNumbersFromLRI() - { - if (DetectionResultColumns[0] == null) - { - return 0; - } - int unadjustedCount = 0; - Codeword[] codewords = DetectionResultColumns[0].Codewords; - for (int codewordsRow = 0; codewordsRow < codewords.Length; codewordsRow++) - { - if (codewords[codewordsRow] == null) - { - continue; - } - int rowIndicatorRowNumber = codewords[codewordsRow].RowNumber; - int invalidRowCounts = 0; - for (int barcodeColumn = 1; barcodeColumn < ColumnCount + 1 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP; barcodeColumn++) - { - Codeword codeword = DetectionResultColumns[barcodeColumn].Codewords[codewordsRow]; - if (codeword != null) - { - invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword); - if (!codeword.HasValidRowNumber) - { - unadjustedCount++; - } - } - } - } - return unadjustedCount; - } - - /// - /// Adjusts the row number if valid. - /// - /// The invalid rows - /// Row indicator row number. - /// Invalid row counts. - /// Codeword. - private static int adjustRowNumberIfValid(int rowIndicatorRowNumber, int invalidRowCounts, Codeword codeword) - { - - if (codeword == null) - { - return invalidRowCounts; - } - if (!codeword.HasValidRowNumber) - { - if (codeword.IsValidRowNumber(rowIndicatorRowNumber)) - { - codeword.RowNumber = rowIndicatorRowNumber; - invalidRowCounts = 0; - } - else - { - ++invalidRowCounts; - } - } - return invalidRowCounts; - } - - /// - /// Adjusts the row numbers. - /// - /// Barcode column. - /// Codewords row. - /// Codewords. - private void adjustRowNumbers(int barcodeColumn, int codewordsRow, Codeword[] codewords) - { - Codeword codeword = codewords[codewordsRow]; - Codeword[] previousColumnCodewords = DetectionResultColumns[barcodeColumn - 1].Codewords; - Codeword[] nextColumnCodewords = previousColumnCodewords; - if (DetectionResultColumns[barcodeColumn + 1] != null) - { - nextColumnCodewords = DetectionResultColumns[barcodeColumn + 1].Codewords; - } - - Codeword[] otherCodewords = new Codeword[14]; - - otherCodewords[2] = previousColumnCodewords[codewordsRow]; - otherCodewords[3] = nextColumnCodewords[codewordsRow]; - - if (codewordsRow > 0) - { - otherCodewords[0] = codewords[codewordsRow - 1]; - otherCodewords[4] = previousColumnCodewords[codewordsRow - 1]; - otherCodewords[5] = nextColumnCodewords[codewordsRow - 1]; - } - if (codewordsRow > 1) - { - otherCodewords[8] = codewords[codewordsRow - 2]; - otherCodewords[10] = previousColumnCodewords[codewordsRow - 2]; - otherCodewords[11] = nextColumnCodewords[codewordsRow - 2]; - } - if (codewordsRow < codewords.Length - 1) - { - otherCodewords[1] = codewords[codewordsRow + 1]; - otherCodewords[6] = previousColumnCodewords[codewordsRow + 1]; - otherCodewords[7] = nextColumnCodewords[codewordsRow + 1]; - } - if (codewordsRow < codewords.Length - 2) - { - otherCodewords[9] = codewords[codewordsRow + 2]; - otherCodewords[12] = previousColumnCodewords[codewordsRow + 2]; - otherCodewords[13] = nextColumnCodewords[codewordsRow + 2]; - } - foreach (Codeword otherCodeword in otherCodewords) - { - if (adjustRowNumber(codeword, otherCodeword)) - { - return; - } - } - } - - /// - /// Adjusts the row number. - /// - /// true, if row number was adjusted, false otherwise. - /// Codeword. - /// Other codeword. - private static bool adjustRowNumber(Codeword codeword, Codeword otherCodeword) - { - if (otherCodeword == null) - { - return false; - } - if (otherCodeword.HasValidRowNumber && otherCodeword.Bucket == codeword.Bucket) - { - codeword.RowNumber = otherCodeword.RowNumber; - return true; - } - return false; - } - - /// - /// Returns a that represents the current . - /// - /// A that represents the current . - public override string ToString() - { - StringBuilder formatter = new StringBuilder(); - DetectionResultColumn rowIndicatorColumn = DetectionResultColumns[0]; - if (rowIndicatorColumn == null) - { - rowIndicatorColumn = DetectionResultColumns[ColumnCount + 1]; - } - for (int codewordsRow = 0; codewordsRow < rowIndicatorColumn.Codewords.Length; codewordsRow++) - { - formatter.AppendFormat(CultureInfo.InvariantCulture, "CW {0,3}:", codewordsRow); - for (int barcodeColumn = 0; barcodeColumn < ColumnCount + 2; barcodeColumn++) - { - if (DetectionResultColumns[barcodeColumn] == null) - { - formatter.Append(" | "); - continue; - } - Codeword codeword = DetectionResultColumns[barcodeColumn].Codewords[codewordsRow]; - if (codeword == null) - { - formatter.Append(" | "); - continue; - } - formatter.AppendFormat(CultureInfo.InvariantCulture, " {0,3}|{1,3}", codeword.RowNumber, codeword.Value); - } - formatter.Append("\n"); - } - - return formatter.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/decoder/DetectionResultColumn.cs b/zxing.core/xx/pdf417/decoder/DetectionResultColumn.cs deleted file mode 100644 index 2afa897..0000000 --- a/zxing.core/xx/pdf417/decoder/DetectionResultColumn.cs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2013 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.Globalization; -using System.Text; - -namespace ZXing.PDF417.Internal -{ - /// - /// Represents a Column in the Detection Result - /// - /// Guenther Grau - public class DetectionResultColumn - { - /// - /// The maximum distance to search in the codeword array in both the positive and negative directions - /// - private const int MAX_NEARBY_DISTANCE = 5; - - /// - /// The Bounding Box around the column (in the BitMatrix) - /// - /// The box. - public BoundingBox Box { get; private set; } - - /// - /// The Codewords the Box encodes for, offset by the Box minY. - /// Remember to Access this ONLY through GetCodeword(imageRow) if you're accessing it in that manner. - /// - /// The codewords. - public Codeword[] Codewords { get; set; } - - // TODO convert this to a dictionary? Dictionary ?? - - /// - /// Initializes a new instance of the class. - /// - /// The Bounding Box around the column (in the BitMatrix) - public DetectionResultColumn(BoundingBox box) - { - this.Box = BoundingBox.Create(box); - this.Codewords = new Codeword[Box.MaxY - Box.MinY + 1]; - } - - /// - /// Converts the Image's Row to the index in the Codewords array - /// - /// The Codeword Index. - /// Image row. - public int IndexForRow(int imageRow) - { - return imageRow - Box.MinY; - } - - /// - /// Converts the Codeword array index into a Row in the Image (BitMatrix) - /// - /// The Image Row. - /// Codeword index. - public int RowForIndex(int codewordIndex) - { - return Box.MinY + codewordIndex; - } - - /// - /// Gets the codeword for a given row - /// - /// The codeword. - /// Image row. - public Codeword getCodeword(int imageRow) - { - return Codewords[imageRowToCodewordIndex(imageRow)]; - } - - /// - /// Gets the codeword closest to the specified row in the image - /// - /// Image row. - public Codeword getCodewordNearby(int imageRow) - { - Codeword codeword = getCodeword(imageRow); - if (codeword != null) - { - return codeword; - } - for (int i = 1; i < MAX_NEARBY_DISTANCE; i++) - { - int nearImageRow = imageRowToCodewordIndex(imageRow) - i; - if (nearImageRow >= 0) - { - codeword = Codewords[nearImageRow]; - if (codeword != null) - { - return codeword; - } - } - nearImageRow = imageRowToCodewordIndex(imageRow) + i; - if (nearImageRow < Codewords.Length) - { - codeword = Codewords[nearImageRow]; - if (codeword != null) - { - return codeword; - } - } - } - return null; - } - - internal int imageRowToCodewordIndex(int imageRow) - { - return imageRow - Box.MinY; - } - - /// - /// Sets the codeword for an image row - /// - /// Image row. - /// Codeword. - public void setCodeword(int imageRow, Codeword codeword) - { - Codewords[IndexForRow(imageRow)] = codeword; - } - - /// - /// Returns a that represents the current . - /// - /// A that represents the current . - public override string ToString() - { - StringBuilder builder = new StringBuilder(); - int row = 0; - foreach (var cw in Codewords) - { - if (cw == null) - { - builder.AppendFormat(CultureInfo.InvariantCulture, "{0,3}: | \n", row++); - } - else - { - builder.AppendFormat(CultureInfo.InvariantCulture, "{0,3}: {1,3}|{2,3}\n", row++, cw.RowNumber, cw.Value); - } - } - return builder.ToString(); - // return "Valid Codewords: " + (from cw in Codewords where cw != null select cw).Count().ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/decoder/DetectionResultRowIndicatorColumn.cs b/zxing.core/xx/pdf417/decoder/DetectionResultRowIndicatorColumn.cs deleted file mode 100644 index e710d1e..0000000 --- a/zxing.core/xx/pdf417/decoder/DetectionResultRowIndicatorColumn.cs +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -using System; - -namespace ZXing.PDF417.Internal -{ - /// - /// Represents a Column in the Detection Result - /// - /// Guenther Grau - public sealed class DetectionResultRowIndicatorColumn : DetectionResultColumn - { - /// - /// Gets or sets a value indicating whether this instance is the left indicator - /// - /// true if this instance is left; otherwise, false. - public bool IsLeft { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// Box. - /// If set to true is left. - public DetectionResultRowIndicatorColumn(BoundingBox box, bool isLeft) - : base(box) - { - this.IsLeft = isLeft; - } - - /// - /// Sets the Row Numbers as Inidicator Columns - /// - public void setRowNumbers() - { - foreach (var cw in Codewords) - { - if (cw != null) - { - cw.setRowNumberAsRowIndicatorColumn(); - } - } - } - - - /// - /// TODO implement properly - /// TODO maybe we should add missing codewords to store the correct row number to make - /// finding row numbers for other columns easier - /// use row height count to make detection of invalid row numbers more reliable - /// - /// The indicator column row numbers. - /// Metadata. - public int adjustCompleteIndicatorColumnRowNumbers(BarcodeMetadata metadata) - { - var codewords = Codewords; - setRowNumbers(); // Assign this as an indicator column - removeIncorrectCodewords(codewords, metadata); - - ResultPoint top = IsLeft ? Box.TopLeft : Box.TopRight; - ResultPoint bottom = IsLeft ? Box.BottomLeft : Box.BottomRight; - - int firstRow = imageRowToCodewordIndex((int) top.Y); - int lastRow = imageRowToCodewordIndex((int) bottom.Y); - - // We need to be careful using the average row height. - // Barcode could be skewed so that we have smaller and taller rows - float averageRowHeight = (lastRow - firstRow)/(float) metadata.RowCount; - - // initialize loop - int barcodeRow = -1; - int maxRowHeight = 1; - int currentRowHeight = 0; - - for (int codewordRow = firstRow; codewordRow < lastRow; codewordRow++) - { - var codeword = codewords[codewordRow]; - if (codeword == null) - { - continue; - } - - // float expectedRowNumber = (codewordsRow - firstRow) / averageRowHeight; - // if (Math.abs(codeword.getRowNumber() - expectedRowNumber) > 2) { - // SimpleLog.log(LEVEL.WARNING, - // "Removing codeword, rowNumberSkew too high, codeword[" + codewordsRow + "]: Expected Row: " + - // expectedRowNumber + ", RealRow: " + codeword.getRowNumber() + ", value: " + codeword.getValue()); - // codewords[codewordsRow] = null; - // } - - int rowDifference = codeword.RowNumber - barcodeRow; - - // TODO improve handling with case where first row indicator doesn't start with 0 - - if (rowDifference == 0) - { - currentRowHeight++; - } - else if (rowDifference == 1) - { - maxRowHeight = Math.Max(maxRowHeight, currentRowHeight); - currentRowHeight = 1; - barcodeRow = codeword.RowNumber; - } - else if (rowDifference < 0 || - codeword.RowNumber >= metadata.RowCount || - rowDifference > codewordRow) - { - codewords[codewordRow] = null; - } - else - { - int checkedRows; - if (maxRowHeight > 2) - { - checkedRows = (maxRowHeight - 2)*rowDifference; - } - else - { - checkedRows = rowDifference; - } - bool closePreviousCodewordFound = checkedRows > codewordRow; - for (int i = 1; i <= checkedRows && !closePreviousCodewordFound; i++) - { - // there must be (height * rowDifference) number of codewords missing. For now we assume height = 1. - // This should hopefully get rid of most problems already. - closePreviousCodewordFound = codewords[codewordRow - i] != null; - } - if (closePreviousCodewordFound) - { - codewords[codewordRow] = null; - } - else - { - barcodeRow = codeword.RowNumber; - currentRowHeight = 1; - } - } - - } - return (int) (averageRowHeight + 0.5); - } - - /// - /// Gets the row heights. - /// - /// The row heights. - public int[] getRowHeights() - { - BarcodeMetadata barcodeMetadata = getBarcodeMetadata(); - if (barcodeMetadata == null) - { - return null; - } - adjustIncompleteIndicatorColumnRowNumbers(barcodeMetadata); - int[] result = new int[barcodeMetadata.RowCount]; - foreach (var codeword in Codewords) - { - if (codeword != null) - { - int rowNumber = codeword.RowNumber; - if (rowNumber >= result.Length) - { - return null; - } - result[rowNumber]++; - } // else throw exception? (or return null) - } - return result; - } - - /// - /// Adjusts the in omplete indicator column row numbers. - /// - /// Metadata. - public int adjustIncompleteIndicatorColumnRowNumbers(BarcodeMetadata metadata) - { - // TODO maybe we should add missing codewords to store the correct row number to make - // finding row numbers for other columns easier - // use row height count to make detection of invalid row numbers more reliable - - ResultPoint top = IsLeft ? Box.TopLeft : Box.TopRight; - ResultPoint bottom = IsLeft ? Box.BottomLeft : Box.BottomRight; - - int firstRow = imageRowToCodewordIndex((int) top.Y); - int lastRow = imageRowToCodewordIndex((int) bottom.Y); - - // We need to be careful using the average row height. - // Barcode could be skewed so that we have smaller and taller rows - float averageRowHeight = (lastRow - firstRow)/(float) metadata.RowCount; - var codewords = Codewords; - - // initialize loop - int barcodeRow = -1; - int maxRowHeight = 1; - int currentRowHeight = 0; - - for (int codewordRow = firstRow; codewordRow < lastRow; codewordRow++) - { - var codeword = codewords[codewordRow]; - if (codeword == null) - { - continue; - } - - codeword.setRowNumberAsRowIndicatorColumn(); - - int rowDifference = codeword.RowNumber - barcodeRow; - - // TODO improve handling with case where first row indicator doesn't start with 0 - - if (rowDifference == 0) - { - currentRowHeight++; - } - else if (rowDifference == 1) - { - maxRowHeight = Math.Max(maxRowHeight, currentRowHeight); - currentRowHeight = 1; - barcodeRow = codeword.RowNumber; - } - else if (codeword.RowNumber > metadata.RowCount) - { - Codewords[codewordRow] = null; - } - else - { - barcodeRow = codeword.RowNumber; - currentRowHeight = 1; - } - - } - return (int) (averageRowHeight + 0.5); - } - - /// - /// Gets the barcode metadata. - /// - /// The barcode metadata. - public BarcodeMetadata getBarcodeMetadata() - { - var codewords = Codewords; - BarcodeValue barcodeColumnCount = new BarcodeValue(); - BarcodeValue barcodeRowCountUpperPart = new BarcodeValue(); - BarcodeValue barcodeRowCountLowerPart = new BarcodeValue(); - BarcodeValue barcodeECLevel = new BarcodeValue(); - foreach (Codeword codeword in codewords) - { - if (codeword == null) - { - continue; - } - codeword.setRowNumberAsRowIndicatorColumn(); - int rowIndicatorValue = codeword.Value%30; - int codewordRowNumber = codeword.RowNumber; - if (!IsLeft) - { - codewordRowNumber += 2; - } - switch (codewordRowNumber%3) - { - case 0: - barcodeRowCountUpperPart.setValue(rowIndicatorValue*3 + 1); - break; - case 1: - barcodeECLevel.setValue(rowIndicatorValue/3); - barcodeRowCountLowerPart.setValue(rowIndicatorValue%3); - break; - case 2: - barcodeColumnCount.setValue(rowIndicatorValue + 1); - break; - } - } - // Maybe we should check if we have ambiguous values? - var barcodeColumnCountValues = barcodeColumnCount.getValue(); - var barcodeRowCountUpperPartValues = barcodeRowCountUpperPart.getValue(); - var barcodeRowCountLowerPartValues = barcodeRowCountLowerPart.getValue(); - var barcodeECLevelValues = barcodeECLevel.getValue(); - if ((barcodeColumnCountValues.Length == 0) || - (barcodeRowCountUpperPartValues.Length == 0) || - (barcodeRowCountLowerPartValues.Length == 0) || - (barcodeECLevelValues.Length == 0) || - barcodeColumnCountValues[0] < 1 || - barcodeRowCountUpperPartValues[0] + barcodeRowCountLowerPartValues[0] < PDF417Common.MIN_ROWS_IN_BARCODE || - barcodeRowCountUpperPartValues[0] + barcodeRowCountLowerPartValues[0] > PDF417Common.MAX_ROWS_IN_BARCODE) - { - return null; - } - var barcodeMetadata = new BarcodeMetadata(barcodeColumnCountValues[0], - barcodeRowCountUpperPartValues[0], - barcodeRowCountLowerPartValues[0], - barcodeECLevelValues[0]); - removeIncorrectCodewords(codewords, barcodeMetadata); - return barcodeMetadata; - } - - /// - /// Prune the codewords which do not match the metadata - /// TODO Maybe we should keep the incorrect codewords for the start and end positions? - /// - /// Codewords. - /// Metadata. - private void removeIncorrectCodewords(Codeword[] codewords, BarcodeMetadata metadata) - { - for (int row = 0; row < codewords.Length; row++) - { - var codeword = codewords[row]; - if (codeword == null) - continue; - - int indicatorValue = codeword.Value%30; - int rowNumber = codeword.RowNumber; - - // Row does not exist in the metadata - if (rowNumber >= metadata.RowCount) // different to java rowNumber > metadata.RowCount - { - codewords[row] = null; // remove this. - continue; - } - - if (!IsLeft) - { - rowNumber += 2; - } - - switch (rowNumber%3) - { - default: - case 0: - if (indicatorValue*3 + 1 != metadata.RowCountUpper) - { - codewords[row] = null; - } - break; - - case 1: - if (indicatorValue%3 != metadata.RowCountLower || - indicatorValue/3 != metadata.ErrorCorrectionLevel) - { - codewords[row] = null; - } - break; - - case 2: - if (indicatorValue + 1 != metadata.ColumnCount) - { - codewords[row] = null; - } - break; - } - - } - } - - /// - /// Returns a that represents the current . - /// - /// A that represents the current . - public override string ToString() - { - return "Is Left: " + IsLeft + " \n" + base.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/decoder/PDF417CodewordDecoder.cs b/zxing.core/xx/pdf417/decoder/PDF417CodewordDecoder.cs deleted file mode 100644 index b43cad3..0000000 --- a/zxing.core/xx/pdf417/decoder/PDF417CodewordDecoder.cs +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2013 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.PDF417.Internal -{ - /// - /// - /// - /// Guenther Grau - /// creatale GmbH (christoph.schulz@creatale.de) - public static class PDF417CodewordDecoder - { - /// - /// The ratios table - /// - private static readonly float[][] RATIOS_TABLE; // = new float[PDF417Common.SYMBOL_TABLE.Length][PDF417Common.BARS_IN_MODULE]; - - /// - /// Initializes the class & Pre-computes the symbol ratio table. - /// - static PDF417CodewordDecoder() - { - // Jagged arrays in Java assign the memory automatically, but C# has no equivalent. (Jon Skeet says so!) - // http://stackoverflow.com/a/5313879/266252 - RATIOS_TABLE = new float[PDF417Common.SYMBOL_TABLE.Length][]; - for (int s = 0; s < RATIOS_TABLE.Length; s++) - { - RATIOS_TABLE[s] = new float[PDF417Common.BARS_IN_MODULE]; - } - - // Pre-computes the symbol ratio table. - for (int i = 0; i < PDF417Common.SYMBOL_TABLE.Length; i++) - { - int currentSymbol = PDF417Common.SYMBOL_TABLE[i]; - int currentBit = currentSymbol & 0x1; - for (int j = 0; j < PDF417Common.BARS_IN_MODULE; j++) - { - float size = 0.0f; - while ((currentSymbol & 0x1) == currentBit) - { - size += 1.0f; - currentSymbol >>= 1; - } - currentBit = currentSymbol & 0x1; - RATIOS_TABLE[i][PDF417Common.BARS_IN_MODULE - j - 1] = size/PDF417Common.MODULES_IN_CODEWORD; - } - } - } - - /// - /// Gets the decoded value. - /// - /// The decoded value. - /// Module bit count. - public static int getDecodedValue(int[] moduleBitCount) - { - int decodedValue = getDecodedCodewordValue(sampleBitCounts(moduleBitCount)); - if (decodedValue != PDF417Common.INVALID_CODEWORD) - { - return decodedValue; - } - return getClosestDecodedValue(moduleBitCount); - } - - /// - /// Samples the bit counts. - /// - /// The bit counts. - /// Module bit count. - private static int[] sampleBitCounts(int[] moduleBitCount) - { - float bitCountSum = PDF417Common.getBitCountSum(moduleBitCount); - int[] result = new int[PDF417Common.BARS_IN_MODULE]; - int bitCountIndex = 0; - int sumPreviousBits = 0; - for (int i = 0; i < PDF417Common.MODULES_IN_CODEWORD; i++) - { - float sampleIndex = - bitCountSum/(2*PDF417Common.MODULES_IN_CODEWORD) + - (i*bitCountSum)/PDF417Common.MODULES_IN_CODEWORD; - if (sumPreviousBits + moduleBitCount[bitCountIndex] <= sampleIndex) - { - sumPreviousBits += moduleBitCount[bitCountIndex]; - bitCountIndex++; - } - result[bitCountIndex]++; - } - return result; - } - - /// - /// Gets the decoded codeword value. - /// - /// The decoded codeword value. - /// Module bit count. - private static int getDecodedCodewordValue(int[] moduleBitCount) - { - int decodedValue = getBitValue(moduleBitCount); - return PDF417Common.getCodeword(decodedValue) == PDF417Common.INVALID_CODEWORD ? PDF417Common.INVALID_CODEWORD : decodedValue; - } - - /// - /// Gets the bit value. - /// - /// The bit value. - /// Module bit count. - private static int getBitValue(int[] moduleBitCount) - { - ulong result = 0; - for (ulong i = 0; i < (ulong) moduleBitCount.Length; i++) - { - for (int bit = 0; bit < moduleBitCount[i]; bit++) - { - result = (result << 1) | (i%2ul == 0ul ? 1ul : 0ul); // C# was warning about using the bit-wise 'OR' here with a mix of int/longs. - } - } - return (int) result; - } - - /// - /// Gets the closest decoded value. - /// - /// The closest decoded value. - /// Module bit count. - private static int getClosestDecodedValue(int[] moduleBitCount) - { - int bitCountSum = PDF417Common.getBitCountSum(moduleBitCount); - float[] bitCountRatios = new float[PDF417Common.BARS_IN_MODULE]; - for (int i = 0; i < bitCountRatios.Length; i++) - { - bitCountRatios[i] = moduleBitCount[i]/(float) bitCountSum; - } - float bestMatchError = float.MaxValue; - int bestMatch = PDF417Common.INVALID_CODEWORD; - for (int j = 0; j < RATIOS_TABLE.Length; j++) - { - float error = 0.0f; - float[] ratioTableRow = RATIOS_TABLE[j]; - for (int k = 0; k < PDF417Common.BARS_IN_MODULE; k++) - { - float diff = ratioTableRow[k] - bitCountRatios[k]; - error += diff*diff; - if (error >= bestMatchError) - { - break; - } - } - if (error < bestMatchError) - { - bestMatchError = error; - bestMatch = PDF417Common.SYMBOL_TABLE[j]; - } - } - return bestMatch; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/decoder/PDF417ScanningDecoder.cs b/zxing.core/xx/pdf417/decoder/PDF417ScanningDecoder.cs deleted file mode 100644 index 63db71f..0000000 --- a/zxing.core/xx/pdf417/decoder/PDF417ScanningDecoder.cs +++ /dev/null @@ -1,916 +0,0 @@ -/* - * Copyright 2013 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.Globalization; -using System.Text; - -using ZXing.Common; -using ZXing.PDF417.Internal.EC; - -namespace ZXing.PDF417.Internal -{ - /// - /// - /// - /// Guenther Grau - public static class PDF417ScanningDecoder - { - private const int CODEWORD_SKEW_SIZE = 2; - - private const int MAX_ERRORS = 3; - private const int MAX_EC_CODEWORDS = 512; - private static readonly ErrorCorrection errorCorrection = new ErrorCorrection(); - - /// - /// Decode the specified image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth - /// and maxCodewordWidth. - /// TODO: don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern - /// columns. That way width can be deducted from the pattern column. - /// This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider - /// than it should be. This can happen if the scanner used a bad blackpoint. - /// - /// Image. - /// Image top left. - /// Image bottom left. - /// Image top right. - /// Image bottom right. - /// Minimum codeword width. - /// Max codeword width. - public static DecoderResult decode(BitMatrix image, - ResultPoint imageTopLeft, - ResultPoint imageBottomLeft, - ResultPoint imageTopRight, - ResultPoint imageBottomRight, - int minCodewordWidth, - int maxCodewordWidth) - { - BoundingBox boundingBox = BoundingBox.Create(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight); - if (boundingBox == null) - return null; - - DetectionResultRowIndicatorColumn leftRowIndicatorColumn = null; - DetectionResultRowIndicatorColumn rightRowIndicatorColumn = null; - DetectionResult detectionResult = null; - for (int i = 0; i < 2; i++) - { - if (imageTopLeft != null) - { - leftRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth); - } - if (imageTopRight != null) - { - rightRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth); - } - detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn); - if (detectionResult == null) - { - // TODO Based on Owen's Comments in , this method has been modified to continue silently - // if a barcode was not decoded where it was detected instead of throwing a new exception object. - return null; - } - if (i == 0 && detectionResult.Box != null && - (detectionResult.Box.MinY < boundingBox.MinY || detectionResult.Box.MaxY > boundingBox.MaxY)) - { - boundingBox = detectionResult.Box; - } - else - { - detectionResult.Box = boundingBox; - break; - } - } - int maxBarcodeColumn = detectionResult.ColumnCount + 1; - detectionResult.DetectionResultColumns[0] = leftRowIndicatorColumn; - - detectionResult.DetectionResultColumns[maxBarcodeColumn] = rightRowIndicatorColumn; - - bool leftToRight = leftRowIndicatorColumn != null; - for (int barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++) - { - int barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount; - if (detectionResult.DetectionResultColumns[barcodeColumn] != null) - { - // This will be the case for the opposite row indicator column, which doesn't need to be decoded again. - continue; - } - DetectionResultColumn detectionResultColumn; - if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn) - { - detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn == 0); - } - else - { - detectionResultColumn = new DetectionResultColumn(boundingBox); - } - detectionResult.DetectionResultColumns[barcodeColumn] = detectionResultColumn; - int startColumn = -1; - int previousStartColumn = startColumn; - // TODO start at a row for which we know the start position, then detect upwards and downwards from there. - for (int imageRow = boundingBox.MinY; imageRow <= boundingBox.MaxY; imageRow++) - { - startColumn = getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight); - if (startColumn < 0 || startColumn > boundingBox.MaxX) - { - if (previousStartColumn == -1) - { - continue; - } - startColumn = previousStartColumn; - } - Codeword codeword = detectCodeword(image, boundingBox.MinX, boundingBox.MaxX, leftToRight, - startColumn, imageRow, minCodewordWidth, maxCodewordWidth); - if (codeword != null) - { - detectionResultColumn.setCodeword(imageRow, codeword); - previousStartColumn = startColumn; - minCodewordWidth = Math.Min(minCodewordWidth, codeword.Width); - maxCodewordWidth = Math.Max(maxCodewordWidth, codeword.Width); - } - } - } - return createDecoderResult(detectionResult); - } - - /// - /// Merge the specified leftRowIndicatorColumn and rightRowIndicatorColumn. - /// - /// Left row indicator column. - /// Right row indicator column. - private static DetectionResult merge(DetectionResultRowIndicatorColumn leftRowIndicatorColumn, - DetectionResultRowIndicatorColumn rightRowIndicatorColumn) - { - if (leftRowIndicatorColumn == null && rightRowIndicatorColumn == null) - { - return null; - } - BarcodeMetadata barcodeMetadata = getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn); - if (barcodeMetadata == null) - { - return null; - } - BoundingBox boundingBox = BoundingBox.merge(adjustBoundingBox(leftRowIndicatorColumn), - adjustBoundingBox(rightRowIndicatorColumn)); - - return new DetectionResult(barcodeMetadata, boundingBox); - } - - /// - /// Adjusts the bounding box. - /// - /// The bounding box. - /// Row indicator column. - private static BoundingBox adjustBoundingBox(DetectionResultRowIndicatorColumn rowIndicatorColumn) - { - if (rowIndicatorColumn == null) - { - return null; - } - int[] rowHeights = rowIndicatorColumn.getRowHeights(); - if (rowHeights == null) - { - return null; - } - int maxRowHeight = getMax(rowHeights); - int missingStartRows = 0; - foreach (int rowHeight in rowHeights) - { - missingStartRows += maxRowHeight - rowHeight; - if (rowHeight > 0) - { - break; - } - } - Codeword[] codewords = rowIndicatorColumn.Codewords; - for (int row = 0; missingStartRows > 0 && codewords[row] == null; row++) - { - missingStartRows--; - } - int missingEndRows = 0; - for (int row = rowHeights.Length - 1; row >= 0; row--) - { - missingEndRows += maxRowHeight - rowHeights[row]; - if (rowHeights[row] > 0) - { - break; - } - } - for (int row = codewords.Length - 1; missingEndRows > 0 && codewords[row] == null; row--) - { - missingEndRows--; - } - return rowIndicatorColumn.Box.addMissingRows(missingStartRows, missingEndRows, rowIndicatorColumn.IsLeft); - } - - private static int getMax(int[] values) - { - int maxValue = -1; - for (var index = values.Length - 1; index >= 0; index--) - { - maxValue = Math.Max(maxValue, values[index]); - } - return maxValue; - } - - /// - /// Gets the barcode metadata. - /// - /// The barcode metadata. - /// Left row indicator column. - /// Right row indicator column. - private static BarcodeMetadata getBarcodeMetadata(DetectionResultRowIndicatorColumn leftRowIndicatorColumn, - DetectionResultRowIndicatorColumn rightRowIndicatorColumn) - { - - BarcodeMetadata leftBarcodeMetadata; - if (leftRowIndicatorColumn == null || - (leftBarcodeMetadata = leftRowIndicatorColumn.getBarcodeMetadata()) == null) - { - return rightRowIndicatorColumn == null ? null : rightRowIndicatorColumn.getBarcodeMetadata(); - } - BarcodeMetadata rightBarcodeMetadata; - if (rightRowIndicatorColumn == null || - (rightBarcodeMetadata = rightRowIndicatorColumn.getBarcodeMetadata()) == null) - { - return leftBarcodeMetadata; - } - - if (leftBarcodeMetadata.ColumnCount != rightBarcodeMetadata.ColumnCount && - leftBarcodeMetadata.ErrorCorrectionLevel != rightBarcodeMetadata.ErrorCorrectionLevel && - leftBarcodeMetadata.RowCount != rightBarcodeMetadata.RowCount) - { - return null; - } - return leftBarcodeMetadata; - } - - /// - /// Gets the row indicator column. - /// - /// The row indicator column. - /// Image. - /// Bounding box. - /// Start point. - /// If set to true left to right. - /// Minimum codeword width. - /// Max codeword width. - private static DetectionResultRowIndicatorColumn getRowIndicatorColumn(BitMatrix image, - BoundingBox boundingBox, - ResultPoint startPoint, - bool leftToRight, - int minCodewordWidth, - int maxCodewordWidth) - { - DetectionResultRowIndicatorColumn rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight); - for (int i = 0; i < 2; i++) - { - int increment = i == 0 ? 1 : -1; - int startColumn = (int) startPoint.X; - for (int imageRow = (int) startPoint.Y; imageRow <= boundingBox.MaxY && - imageRow >= boundingBox.MinY; imageRow += increment) - { - Codeword codeword = detectCodeword(image, 0, image.Width, leftToRight, startColumn, imageRow, - minCodewordWidth, maxCodewordWidth); - if (codeword != null) - { - rowIndicatorColumn.setCodeword(imageRow, codeword); - if (leftToRight) - { - startColumn = codeword.StartX; - } - else - { - startColumn = codeword.EndX; - } - } - } - } - return rowIndicatorColumn; - } - - /// - /// Adjusts the codeword count. - /// - /// Detection result. - /// Barcode matrix. - private static bool adjustCodewordCount(DetectionResult detectionResult, BarcodeValue[][] barcodeMatrix) - { - int[] numberOfCodewords = barcodeMatrix[0][1].getValue(); - int calculatedNumberOfCodewords = detectionResult.ColumnCount* - detectionResult.RowCount - - getNumberOfECCodeWords(detectionResult.ErrorCorrectionLevel); - if (numberOfCodewords.Length == 0) - { - if (calculatedNumberOfCodewords < 1 || calculatedNumberOfCodewords > PDF417Common.MAX_CODEWORDS_IN_BARCODE) - { - return false; - } - barcodeMatrix[0][1].setValue(calculatedNumberOfCodewords); - } - else if (numberOfCodewords[0] != calculatedNumberOfCodewords) - { - // The calculated one is more reliable as it is derived from the row indicator columns - barcodeMatrix[0][1].setValue(calculatedNumberOfCodewords); - } - - return true; - } - - /// - /// Creates the decoder result. - /// - /// The decoder result. - /// Detection result. - private static DecoderResult createDecoderResult(DetectionResult detectionResult) - { - BarcodeValue[][] barcodeMatrix = createBarcodeMatrix(detectionResult); - if (barcodeMatrix == null) - return null; - - if (!adjustCodewordCount(detectionResult, barcodeMatrix)) - { - return null; - } - List erasures = new List(); - int[] codewords = new int[detectionResult.RowCount*detectionResult.ColumnCount]; - List ambiguousIndexValuesList = new List(); - List ambiguousIndexesList = new List(); - for (int row = 0; row < detectionResult.RowCount; row++) - { - for (int column = 0; column < detectionResult.ColumnCount; column++) - { - int[] values = barcodeMatrix[row][column + 1].getValue(); - int codewordIndex = row*detectionResult.ColumnCount + column; - if (values.Length == 0) - { - erasures.Add(codewordIndex); - } - else if (values.Length == 1) - { - codewords[codewordIndex] = values[0]; - } - else - { - ambiguousIndexesList.Add(codewordIndex); - ambiguousIndexValuesList.Add(values); - } - } - } - int[][] ambiguousIndexValues = new int[ambiguousIndexValuesList.Count][]; - for (int i = 0; i < ambiguousIndexValues.Length; i++) - { - ambiguousIndexValues[i] = ambiguousIndexValuesList[i]; - } - return createDecoderResultFromAmbiguousValues(detectionResult.ErrorCorrectionLevel, codewords, - erasures.ToArray(), ambiguousIndexesList.ToArray(), ambiguousIndexValues); - } - - /// - /// This method deals with the fact, that the decoding process doesn't always yield a single most likely value. The - /// current error correction implementation doesn't deal with erasures very well, so it's better to provide a value - /// for these ambiguous codewords instead of treating it as an erasure. The problem is that we don't know which of - /// the ambiguous values to choose. We try decode using the first value, and if that fails, we use another of the - /// ambiguous values and try to decode again. This usually only happens on very hard to read and decode barcodes, - /// so decoding the normal barcodes is not affected by this. - /// - /// The decoder result from ambiguous values. - /// Ec level. - /// Codewords. - /// contains the indexes of erasures. - /// array with the indexes that have more than one most likely value. - /// two dimensional array that contains the ambiguous values. The first dimension must - /// be the same Length as the ambiguousIndexes array. - private static DecoderResult createDecoderResultFromAmbiguousValues(int ecLevel, - int[] codewords, - int[] erasureArray, - int[] ambiguousIndexes, - int[][] ambiguousIndexValues) - { - int[] ambiguousIndexCount = new int[ambiguousIndexes.Length]; - - int tries = 100; - while (tries-- > 0) - { - for (int i = 0; i < ambiguousIndexCount.Length; i++) - { - codewords[ambiguousIndexes[i]] = ambiguousIndexValues[i][ambiguousIndexCount[i]]; - } - try - { - var result = decodeCodewords(codewords, ecLevel, erasureArray); - if (result != null) - return result; - } - catch (ReaderException) - { - // ignored, should not happen - } - if (ambiguousIndexCount.Length == 0) - { - return null; - } - for (int i = 0; i < ambiguousIndexCount.Length; i++) - { - if (ambiguousIndexCount[i] < ambiguousIndexValues[i].Length - 1) - { - ambiguousIndexCount[i]++; - break; - } - else - { - ambiguousIndexCount[i] = 0; - if (i == ambiguousIndexCount.Length - 1) - { - return null; - } - } - } - } - return null; - } - - /// - /// Creates the barcode matrix. - /// - /// The barcode matrix. - /// Detection result. - private static BarcodeValue[][] createBarcodeMatrix(DetectionResult detectionResult) - { - // Manually setup Jagged Array in C# - var barcodeMatrix = new BarcodeValue[detectionResult.RowCount][]; - for (int row = 0; row < barcodeMatrix.Length; row++) - { - barcodeMatrix[row] = new BarcodeValue[detectionResult.ColumnCount + 2]; - for (int col = 0; col < barcodeMatrix[row].Length; col++) - { - barcodeMatrix[row][col] = new BarcodeValue(); - } - } - - int column = 0; - foreach (DetectionResultColumn detectionResultColumn in detectionResult.getDetectionResultColumns()) - { - if (detectionResultColumn != null) - { - foreach (Codeword codeword in detectionResultColumn.Codewords) - { - if (codeword != null) - { - int rowNumber = codeword.RowNumber; - if (rowNumber >= 0) - { - if (rowNumber >= barcodeMatrix.Length) - { - return null; - } - barcodeMatrix[rowNumber][column].setValue(codeword.Value); - } - } - } - } - column++; - } - - return barcodeMatrix; - } - - /// - /// Tests to see if the Barcode Column is Valid - /// - /// true, if barcode column is valid, false otherwise. - /// Detection result. - /// Barcode column. - private static bool isValidBarcodeColumn(DetectionResult detectionResult, int barcodeColumn) - { - return (barcodeColumn >= 0) && (barcodeColumn < detectionResult.DetectionResultColumns.Length); - } - - /// - /// Gets the start column. - /// - /// The start column. - /// Detection result. - /// Barcode column. - /// Image row. - /// If set to true left to right. - private static int getStartColumn(DetectionResult detectionResult, - int barcodeColumn, - int imageRow, - bool leftToRight) - { - int offset = leftToRight ? 1 : -1; - Codeword codeword = null; - if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) - { - codeword = detectionResult.DetectionResultColumns[barcodeColumn - offset].getCodeword(imageRow); - } - if (codeword != null) - { - return leftToRight ? codeword.EndX : codeword.StartX; - } - codeword = detectionResult.DetectionResultColumns[barcodeColumn].getCodewordNearby(imageRow); - if (codeword != null) - { - return leftToRight ? codeword.StartX : codeword.EndX; - } - if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) - { - codeword = detectionResult.DetectionResultColumns[barcodeColumn - offset].getCodewordNearby(imageRow); - } - if (codeword != null) - { - return leftToRight ? codeword.EndX : codeword.StartX; - } - int skippedColumns = 0; - - while (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) - { - barcodeColumn -= offset; - foreach (Codeword previousRowCodeword in detectionResult.DetectionResultColumns[barcodeColumn].Codewords) - { - if (previousRowCodeword != null) - { - return (leftToRight ? previousRowCodeword.EndX : previousRowCodeword.StartX) + - offset* - skippedColumns* - (previousRowCodeword.EndX - previousRowCodeword.StartX); - } - } - skippedColumns++; - } - return leftToRight ? detectionResult.Box.MinX : detectionResult.Box.MaxX; - } - - /// - /// Detects the codeword. - /// - /// The codeword. - /// Image. - /// Minimum column. - /// Max column. - /// If set to true left to right. - /// Start column. - /// Image row. - /// Minimum codeword width. - /// Max codeword width. - private static Codeword detectCodeword(BitMatrix image, - int minColumn, - int maxColumn, - bool leftToRight, - int startColumn, - int imageRow, - int minCodewordWidth, - int maxCodewordWidth) - { - startColumn = adjustCodewordStartColumn(image, minColumn, maxColumn, leftToRight, startColumn, imageRow); - // we usually know fairly exact now how long a codeword is. We should provide minimum and maximum expected length - // and try to adjust the read pixels, e.g. remove single pixel errors or try to cut off exceeding pixels. - // min and maxCodewordWidth should not be used as they are calculated for the whole barcode an can be inaccurate - // for the current position - int[] moduleBitCount = getModuleBitCount(image, minColumn, maxColumn, leftToRight, startColumn, imageRow); - if (moduleBitCount == null) - { - return null; - } - int endColumn; - int codewordBitCount = PDF417Common.getBitCountSum(moduleBitCount); - if (leftToRight) - { - endColumn = startColumn + codewordBitCount; - } - else - { - for (int i = 0; i < (moduleBitCount.Length >> 1); i++) - { - int tmpCount = moduleBitCount[i]; - moduleBitCount[i] = moduleBitCount[moduleBitCount.Length - 1 - i]; - moduleBitCount[moduleBitCount.Length - 1 - i] = tmpCount; - } - endColumn = startColumn; - startColumn = endColumn - codewordBitCount; - } - // TODO implement check for width and correction of black and white bars - // use start (and maybe stop pattern) to determine if blackbars are wider than white bars. If so, adjust. - // should probably done only for codewords with a lot more than 17 bits. - // The following fixes 10-1.png, which has wide black bars and small white bars - // for (int i = 0; i < moduleBitCount.Length; i++) { - // if (i % 2 == 0) { - // moduleBitCount[i]--; - // } else { - // moduleBitCount[i]++; - // } - // } - - // We could also use the width of surrounding codewords for more accurate results, but this seems - // sufficient for now - if (!checkCodewordSkew(codewordBitCount, minCodewordWidth, maxCodewordWidth)) - { - // We could try to use the startX and endX position of the codeword in the same column in the previous row, - // create the bit count from it and normalize it to 8. This would help with single pixel errors. - return null; - } - - int decodedValue = PDF417CodewordDecoder.getDecodedValue(moduleBitCount); - int codeword = PDF417Common.getCodeword(decodedValue); - if (codeword == -1) - { - return null; - } - return new Codeword(startColumn, endColumn, getCodewordBucketNumber(decodedValue), codeword); - } - - /// - /// Gets the module bit count. - /// - /// The module bit count. - /// Image. - /// Minimum column. - /// Max column. - /// If set to true left to right. - /// Start column. - /// Image row. - private static int[] getModuleBitCount(BitMatrix image, - int minColumn, - int maxColumn, - bool leftToRight, - int startColumn, - int imageRow) - { - int imageColumn = startColumn; - int[] moduleBitCount = new int[8]; - int moduleNumber = 0; - int increment = leftToRight ? 1 : -1; - bool previousPixelValue = leftToRight; - while (((leftToRight && imageColumn < maxColumn) || (!leftToRight && imageColumn >= minColumn)) && - moduleNumber < moduleBitCount.Length) - { - if (image[imageColumn, imageRow] == previousPixelValue) - { - moduleBitCount[moduleNumber]++; - imageColumn += increment; - } - else - { - moduleNumber++; - previousPixelValue = !previousPixelValue; - } - } - if (moduleNumber == moduleBitCount.Length || - (((leftToRight && imageColumn == maxColumn) || (!leftToRight && imageColumn == minColumn)) && moduleNumber == moduleBitCount.Length - 1)) - { - return moduleBitCount; - } - return null; - } - - /// - /// Gets the number of EC code words. - /// - /// The number of EC code words. - /// Barcode EC level. - private static int getNumberOfECCodeWords(int barcodeECLevel) - { - return 2 << barcodeECLevel; - } - - /// - /// Adjusts the codeword start column. - /// - /// The codeword start column. - /// Image. - /// Minimum column. - /// Max column. - /// If set to true left to right. - /// Codeword start column. - /// Image row. - private static int adjustCodewordStartColumn(BitMatrix image, - int minColumn, - int maxColumn, - bool leftToRight, - int codewordStartColumn, - int imageRow) - { - int correctedStartColumn = codewordStartColumn; - int increment = leftToRight ? -1 : 1; - // there should be no black pixels before the start column. If there are, then we need to start earlier. - for (int i = 0; i < 2; i++) - { - while (((leftToRight && correctedStartColumn >= minColumn) || (!leftToRight && correctedStartColumn < maxColumn)) && - leftToRight == image[correctedStartColumn, imageRow]) - { - if (Math.Abs(codewordStartColumn - correctedStartColumn) > CODEWORD_SKEW_SIZE) - { - return codewordStartColumn; - } - correctedStartColumn += increment; - } - increment = -increment; - leftToRight = !leftToRight; - } - return correctedStartColumn; - } - - /// - /// Checks the codeword for any skew. - /// - /// true, if codeword is within the skew, false otherwise. - /// Codeword size. - /// Minimum codeword width. - /// Max codeword width. - private static bool checkCodewordSkew(int codewordSize, int minCodewordWidth, int maxCodewordWidth) - { - return minCodewordWidth - CODEWORD_SKEW_SIZE <= codewordSize && - codewordSize <= maxCodewordWidth + CODEWORD_SKEW_SIZE; - } - - /// - /// Decodes the codewords. - /// - /// The codewords. - /// Codewords. - /// Ec level. - /// Erasures. - private static DecoderResult decodeCodewords(int[] codewords, int ecLevel, int[] erasures) - { - if (codewords.Length == 0) - { - return null; - } - - int numECCodewords = 1 << (ecLevel + 1); - - int correctedErrorsCount = correctErrors(codewords, erasures, numECCodewords); - if (correctedErrorsCount < 0) - { - return null; - } - if (!verifyCodewordCount(codewords, numECCodewords)) - { - return null; - } - - // Decode the codewords - DecoderResult decoderResult = DecodedBitStreamParser.decode(codewords, ecLevel.ToString()); - if (decoderResult != null) - { - decoderResult.ErrorsCorrected = correctedErrorsCount; - decoderResult.Erasures = erasures.Length; - } - return decoderResult; - } - - /// - /// Given data and error-correction codewords received, possibly corrupted by errors, attempts to - /// correct the errors in-place. - /// - /// The errors. - /// data and error correction codewords. - /// positions of any known erasures. - /// number of error correction codewords that are available in codewords. - private static int correctErrors(int[] codewords, int[] erasures, int numECCodewords) - { - if (erasures != null && - erasures.Length > numECCodewords/2 + MAX_ERRORS || - numECCodewords < 0 || - numECCodewords > MAX_EC_CODEWORDS) - { - // Too many errors or EC Codewords is corrupted - return -1; - - } - int errorCount; - if (!errorCorrection.decode(codewords, numECCodewords, erasures, out errorCount)) - { - return -1; - } - return errorCount; - } - - /// - /// Verifies that all is well with the the codeword array. - /// - /// Codewords. - /// Number EC codewords. - private static bool verifyCodewordCount(int[] codewords, int numECCodewords) - { - if (codewords.Length < 4) - { - // Codeword array size should be at least 4 allowing for - // Count CW, At least one Data CW, Error Correction CW, Error Correction CW - return false; - } - // The first codeword, the Symbol Length Descriptor, shall always encode the total number of data - // codewords in the symbol, including the Symbol Length Descriptor itself, data codewords and pad - // codewords, but excluding the number of error correction codewords. - int numberOfCodewords = codewords[0]; - if (numberOfCodewords > codewords.Length) - { - return false; - } - if (numberOfCodewords == 0) - { - // Reset to the Length of the array - 8 (Allow for at least level 3 Error Correction (8 Error Codewords) - if (numECCodewords < codewords.Length) - { - codewords[0] = codewords.Length - numECCodewords; - } - else - { - return false; - } - } - - return true; - } - - /// - /// Gets the bit count for codeword. - /// - /// The bit count for codeword. - /// Codeword. - private static int[] getBitCountForCodeword(int codeword) - { - int[] result = new int[8]; - int previousValue = 0; - int i = result.Length - 1; - while (true) - { - if ((codeword & 0x1) != previousValue) - { - previousValue = codeword & 0x1; - i--; - if (i < 0) - { - break; - } - } - result[i]++; - codeword >>= 1; - } - return result; - } - - /// - /// Gets the codeword bucket number. - /// - /// The codeword bucket number. - /// Codeword. - private static int getCodewordBucketNumber(int codeword) - { - return getCodewordBucketNumber(getBitCountForCodeword(codeword)); - } - - /// - /// Gets the codeword bucket number. - /// - /// The codeword bucket number. - /// Module bit count. - private static int getCodewordBucketNumber(int[] moduleBitCount) - { - return (moduleBitCount[0] - moduleBitCount[2] + moduleBitCount[4] - moduleBitCount[6] + 9)%9; - } - - /// - /// Returns a that represents the jagged array. - /// - /// A that represents the jagged array. - /// Barcode matrix as a jagged array. - public static String ToString(BarcodeValue[][] barcodeMatrix) - { - StringBuilder formatter = new StringBuilder(); - for (int row = 0; row < barcodeMatrix.Length; row++) - { - formatter.AppendFormat(CultureInfo.InvariantCulture, "Row {0,2}: ", row); - for (int column = 0; column < barcodeMatrix[row].Length; column++) - { - BarcodeValue barcodeValue = barcodeMatrix[row][column]; - int[] values = barcodeValue.getValue(); - if (values.Length == 0) - { - formatter.Append(" "); - } - else - { - formatter.AppendFormat(CultureInfo.InvariantCulture, "{0,4}({1,2})", values[0], barcodeValue.getConfidence(values[0])); - } - } - formatter.Append("\n"); - } - return formatter.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/decoder/ec/ErrorCorrection.cs b/zxing.core/xx/pdf417/decoder/ec/ErrorCorrection.cs deleted file mode 100644 index d0a72b9..0000000 --- a/zxing.core/xx/pdf417/decoder/ec/ErrorCorrection.cs +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace ZXing.PDF417.Internal.EC -{ - /// - ///

PDF417 error correction implementation.

- ///

This example - /// is quite useful in understanding the algorithm.

- /// Sean Owen - /// - ///
- public sealed class ErrorCorrection - { - private readonly ModulusGF field; - - /// - /// Initializes a new instance of the class. - /// - public ErrorCorrection() - { - this.field = ModulusGF.PDF417_GF; - } - - /// - /// Decodes the specified received. - /// - /// received codewords - /// number of those codewords used for EC - /// location of erasures - /// The error locations count. - /// - public bool decode(int[] received, int numECCodewords, int[] erasures, out int errorLocationsCount) - { - ModulusPoly poly = new ModulusPoly(field, received); - int[] S = new int[numECCodewords]; - bool error = false; - errorLocationsCount = 0; - for (int i = numECCodewords; i > 0; i--) - { - int eval = poly.evaluateAt(field.exp(i)); - S[numECCodewords - i] = eval; - if (eval != 0) - { - error = true; - } - } - - if (!error) - { - return true; - } - - ModulusPoly knownErrors = field.One; - if (erasures != null) - { - foreach (int erasure in erasures) - { - int b = field.exp(received.Length - 1 - erasure); - // Add (1 - bx) term: - ModulusPoly term = new ModulusPoly(field, new int[] {field.subtract(0, b), 1}); - knownErrors = knownErrors.multiply(term); - } - } - - ModulusPoly syndrome = new ModulusPoly(field, S); - //syndrome = syndrome.multiply(knownErrors); - - ModulusPoly[] sigmaOmega = runEuclideanAlgorithm(field.buildMonomial(numECCodewords, 1), syndrome, numECCodewords); - - if (sigmaOmega == null) - { - return false; - } - - ModulusPoly sigma = sigmaOmega[0]; - ModulusPoly omega = sigmaOmega[1]; - - if (sigma == null || omega == null) - { - return false; - } - - //sigma = sigma.multiply(knownErrors); - - int[] errorLocations = findErrorLocations(sigma); - - if (errorLocations == null) - { - return false; - } - - int[] errorMagnitudes = findErrorMagnitudes(omega, sigma, errorLocations); - - for (int i = 0; i < errorLocations.Length; i++) - { - int position = received.Length - 1 - field.log(errorLocations[i]); - if (position < 0) - { - return false; - - } - received[position] = field.subtract(received[position], errorMagnitudes[i]); - } - errorLocationsCount = errorLocations.Length; - return true; - } - - /// - /// Runs the euclidean algorithm (Greatest Common Divisor) until r's degree is less than R/2 - /// - /// The euclidean algorithm. - private ModulusPoly[] runEuclideanAlgorithm(ModulusPoly a, ModulusPoly b, int R) - { - // Assume a's degree is >= b's - if (a.Degree < b.Degree) - { - ModulusPoly temp = a; - a = b; - b = temp; - } - - ModulusPoly rLast = a; - ModulusPoly r = b; - ModulusPoly tLast = field.Zero; - ModulusPoly t = field.One; - - // Run Euclidean algorithm until r's degree is less than R/2 - while (r.Degree >= R / 2) - { - ModulusPoly rLastLast = rLast; - ModulusPoly tLastLast = tLast; - rLast = r; - tLast = t; - - // Divide rLastLast by rLast, with quotient in q and remainder in r - if (rLast.isZero) - { - // Oops, Euclidean algorithm already terminated? - return null; - } - r = rLastLast; - ModulusPoly q = field.Zero; - int denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree); - int dltInverse = field.inverse(denominatorLeadingTerm); - while (r.Degree >= rLast.Degree && !r.isZero) - { - int degreeDiff = r.Degree - rLast.Degree; - int scale = field.multiply(r.getCoefficient(r.Degree), dltInverse); - q = q.add(field.buildMonomial(degreeDiff, scale)); - r = r.subtract(rLast.multiplyByMonomial(degreeDiff, scale)); - } - - t = q.multiply(tLast).subtract(tLastLast).getNegative(); - } - - int sigmaTildeAtZero = t.getCoefficient(0); - if (sigmaTildeAtZero == 0) - { - return null; - } - - int inverse = field.inverse(sigmaTildeAtZero); - ModulusPoly sigma = t.multiply(inverse); - ModulusPoly omega = r.multiply(inverse); - return new ModulusPoly[] { sigma, omega }; - } - - /// - /// Finds the error locations as a direct application of Chien's search - /// - /// The error locations. - /// Error locator. - private int[] findErrorLocations(ModulusPoly errorLocator) - { - // This is a direct application of Chien's search - int numErrors = errorLocator.Degree; - int[] result = new int[numErrors]; - int e = 0; - for (int i = 1; i < field.Size && e < numErrors; i++) - { - if (errorLocator.evaluateAt(i) == 0) - { - result[e] = field.inverse(i); - e++; - } - } - if (e != numErrors) - { - return null; - } - return result; - } - - /// - /// Finds the error magnitudes by directly applying Forney's Formula - /// - /// The error magnitudes. - /// Error evaluator. - /// Error locator. - /// Error locations. - private int[] findErrorMagnitudes(ModulusPoly errorEvaluator, - ModulusPoly errorLocator, - int[] errorLocations) - { - int errorLocatorDegree = errorLocator.Degree; - int[] formalDerivativeCoefficients = new int[errorLocatorDegree]; - for (int i = 1; i <= errorLocatorDegree; i++) - { - formalDerivativeCoefficients[errorLocatorDegree - i] = - field.multiply(i, errorLocator.getCoefficient(i)); - } - ModulusPoly formalDerivative = new ModulusPoly(field, formalDerivativeCoefficients); - - // This is directly applying Forney's Formula - int s = errorLocations.Length; - int[] result = new int[s]; - for (int i = 0; i < s; i++) - { - int xiInverse = field.inverse(errorLocations[i]); - int numerator = field.subtract(0, errorEvaluator.evaluateAt(xiInverse)); - int denominator = field.inverse(formalDerivative.evaluateAt(xiInverse)); - result[i] = field.multiply(numerator, denominator); - } - return result; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/decoder/ec/ModulusGF.cs b/zxing.core/xx/pdf417/decoder/ec/ModulusGF.cs deleted file mode 100644 index ad97319..0000000 --- a/zxing.core/xx/pdf417/decoder/ec/ModulusGF.cs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; - -namespace ZXing.PDF417.Internal.EC -{ - /// - ///

A field based on powers of a generator integer, modulo some modulus.

- /// @see com.google.zxing.common.reedsolomon.GenericGF - ///
- /// Sean Owen - internal sealed class ModulusGF - { - public static ModulusGF PDF417_GF = new ModulusGF(PDF417Common.NUMBER_OF_CODEWORDS, 3); - - private readonly int[] expTable; - private readonly int[] logTable; - public ModulusPoly Zero { get; private set; } - public ModulusPoly One { get; private set; } - private readonly int modulus; - - public ModulusGF(int modulus, int generator) - { - this.modulus = modulus; - expTable = new int[modulus]; - logTable = new int[modulus]; - int x = 1; - for (int i = 0; i < modulus; i++) - { - expTable[i] = x; - x = (x * generator) % modulus; - } - for (int i = 0; i < modulus - 1; i++) - { - logTable[expTable[i]] = i; - } - // logTable[0] == 0 but this should never be used - Zero = new ModulusPoly(this, new int[] {0}); - One = new ModulusPoly(this, new int[] {1}); - } - - internal ModulusPoly buildMonomial(int degree, int coefficient) - { - if (degree < 0) - { - throw new ArgumentException(); - } - if (coefficient == 0) - { - return Zero; - } - int[] coefficients = new int[degree + 1]; - coefficients[0] = coefficient; - return new ModulusPoly(this, coefficients); - } - - internal int add(int a, int b) - { - return (a + b)%modulus; - } - - internal int subtract(int a, int b) - { - return (modulus + a - b)%modulus; - } - - internal int exp(int a) - { - return expTable[a]; - } - - internal int log(int a) - { - if (a == 0) - { - throw new ArgumentException(); - } - return logTable[a]; - } - - internal int inverse(int a) - { - if (a == 0) - { - throw new ArithmeticException(); - } - return expTable[modulus - logTable[a] - 1]; - } - - internal int multiply(int a, int b) - { - if (a == 0 || b == 0) - { - return 0; - } - return expTable[(logTable[a] + logTable[b]) % (modulus - 1)]; - } - - internal int Size - { - get - { - return modulus; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/decoder/ec/ModulusPoly.cs b/zxing.core/xx/pdf417/decoder/ec/ModulusPoly.cs deleted file mode 100644 index 3e5d8ed..0000000 --- a/zxing.core/xx/pdf417/decoder/ec/ModulusPoly.cs +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Text; - -namespace ZXing.PDF417.Internal.EC -{ - /// - /// - /// - /// Sean Owen - internal sealed class ModulusPoly - { - private readonly ModulusGF field; - private readonly int[] coefficients; - - public ModulusPoly(ModulusGF field, int[] coefficients) - { - if (coefficients.Length == 0) - { - throw new ArgumentException(); - } - this.field = field; - int coefficientsLength = coefficients.Length; - if (coefficientsLength > 1 && coefficients[0] == 0) - { - // Leading term must be non-zero for anything except the constant polynomial "0" - int firstNonZero = 1; - while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) - { - firstNonZero++; - } - if (firstNonZero == coefficientsLength) - { - this.coefficients = new int[]{0}; - } - else - { - this.coefficients = new int[coefficientsLength - firstNonZero]; - Array.Copy(coefficients, - firstNonZero, - this.coefficients, - 0, - this.coefficients.Length); - } - } - else - { - this.coefficients = coefficients; - } - } - - /// - /// Gets the coefficients. - /// - /// The coefficients. - internal int[] Coefficients - { - get { return coefficients; } - } - - /// - /// degree of this polynomial - /// - internal int Degree - { - get - { - return coefficients.Length - 1; - } - } - - /// - /// Gets a value indicating whether this instance is zero. - /// - /// true if this polynomial is the monomial "0" - /// - internal bool isZero - { - get { return coefficients[0] == 0; } - } - - /// - /// coefficient of x^degree term in this polynomial - /// - /// The degree. - /// coefficient of x^degree term in this polynomial - internal int getCoefficient(int degree) - { - return coefficients[coefficients.Length - 1 - degree]; - } - - /// - /// evaluation of this polynomial at a given point - /// - /// A. - /// evaluation of this polynomial at a given point - internal int evaluateAt(int a) - { - if (a == 0) - { - // Just return the x^0 coefficient - return getCoefficient(0); - } - int size = coefficients.Length; - int result = 0; - if (a == 1) - { - // Just the sum of the coefficients - foreach (var coefficient in coefficients) - { - result = field.add(result, coefficient); - } - return result; - } - result = coefficients[0]; - for (int i = 1; i < size; i++) - { - result = field.add(field.multiply(a, result), coefficients[i]); - } - return result; - } - - /// - /// Adds another Modulus - /// - /// Other. - internal ModulusPoly add(ModulusPoly other) - { - if (!field.Equals(other.field)) - { - throw new ArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (isZero) - { - return other; - } - if (other.isZero) - { - return this; - } - - int[] smallerCoefficients = this.coefficients; - int[] largerCoefficients = other.coefficients; - if (smallerCoefficients.Length > largerCoefficients.Length) - { - int[] temp = smallerCoefficients; - smallerCoefficients = largerCoefficients; - largerCoefficients = temp; - } - int[] sumDiff = new int[largerCoefficients.Length]; - int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length; - // Copy high-order terms only found in higher-degree polynomial's coefficients - Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff); - - for (int i = lengthDiff; i < largerCoefficients.Length; i++) - { - sumDiff[i] = field.add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]); - } - - return new ModulusPoly(field, sumDiff); - } - - /// - /// Subtract another Modulus - /// - /// Other. - internal ModulusPoly subtract(ModulusPoly other) - { - if (!field.Equals(other.field)) - { - throw new ArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (other.isZero) - { - return this; - } - return add(other.getNegative()); - } - - /// - /// Multiply by another Modulus - /// - /// Other. - internal ModulusPoly multiply(ModulusPoly other) - { - if (!field.Equals(other.field)) - { - throw new ArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (isZero || other.isZero) - { - return field.Zero; - } - int[] aCoefficients = this.coefficients; - int aLength = aCoefficients.Length; - int[] bCoefficients = other.coefficients; - int bLength = bCoefficients.Length; - int[] product = new int[aLength + bLength - 1]; - for (int i = 0; i < aLength; i++) - { - int aCoeff = aCoefficients[i]; - for (int j = 0; j < bLength; j++) - { - product[i + j] = field.add(product[i + j], field.multiply(aCoeff, bCoefficients[j])); - } - } - return new ModulusPoly(field, product); - } - - /// - /// Returns a Negative version of this instance - /// - internal ModulusPoly getNegative() - { - int size = coefficients.Length; - int[] negativeCoefficients = new int[size]; - for (int i = 0; i < size; i++) - { - negativeCoefficients[i] = field.subtract(0, coefficients[i]); - } - return new ModulusPoly(field, negativeCoefficients); - } - - /// - /// Multiply by a Scalar. - /// - /// Scalar. - internal ModulusPoly multiply(int scalar) - { - if (scalar == 0) - { - return field.Zero; - } - if (scalar == 1) - { - return this; - } - int size = coefficients.Length; - int[] product = new int[size]; - for (int i = 0; i < size; i++) - { - product[i] = field.multiply(coefficients[i], scalar); - } - return new ModulusPoly(field, product); - } - - /// - /// Multiplies by a Monomial - /// - /// The by monomial. - /// Degree. - /// Coefficient. - internal ModulusPoly multiplyByMonomial(int degree, int coefficient) - { - if (degree < 0) - { - throw new ArgumentException(); - } - if (coefficient == 0) - { - return field.Zero; - } - int size = coefficients.Length; - int[] product = new int[size + degree]; - for (int i = 0; i < size; i++) - { - product[i] = field.multiply(coefficients[i], coefficient); - } - return new ModulusPoly(field, product); - } - - /// - /// Divide by another modulus - /// - /// Other. - internal ModulusPoly[] divide(ModulusPoly other) - { - if (!field.Equals(other.field)) - { - throw new ArgumentException("ModulusPolys do not have same ModulusGF field"); - } - if (other.isZero) - { - throw new DivideByZeroException(); - } - - ModulusPoly quotient = field.Zero; - ModulusPoly remainder = this; - - int denominatorLeadingTerm = other.getCoefficient(other.Degree); - int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm); - - while (remainder.Degree >= other.Degree && !remainder.isZero) - { - int degreeDifference = remainder.Degree - other.Degree; - int scale = field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm); - ModulusPoly term = other.multiplyByMonomial(degreeDifference, scale); - ModulusPoly iterationQuotient = field.buildMonomial(degreeDifference, scale); - quotient = quotient.add(iterationQuotient); - remainder = remainder.subtract(term); - } - - return new ModulusPoly[] { quotient, remainder }; - } - - /// - /// Returns a that represents the current . - /// - /// A that represents the current . - public override String ToString() - { - var result = new StringBuilder(8 * Degree); - for (int degree = Degree; degree >= 0; degree--) - { - int coefficient = getCoefficient(degree); - if (coefficient != 0) - { - if (coefficient < 0) - { - result.Append(" - "); - coefficient = -coefficient; - } - else - { - if (result.Length > 0) - { - result.Append(" + "); - } - } - if (degree == 0 || coefficient != 1) - { - result.Append(coefficient); - } - if (degree != 0) - { - if (degree == 1) - { - result.Append('x'); - } - else - { - result.Append("x^"); - result.Append(degree); - } - } - } - } - return result.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/detector/Detector.cs b/zxing.core/xx/pdf417/detector/Detector.cs deleted file mode 100644 index 91f6d60..0000000 --- a/zxing.core/xx/pdf417/detector/Detector.cs +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.PDF417.Internal -{ - /// - ///

Encapsulates logic that can detect a PDF417 Code in an image, even if the - /// PDF417 Code is rotated or skewed, or partially obscured.

- /// - /// SITA Lab (kevin.osullivan@sita.aero) - /// dswitkin@google.com (Daniel Switkin) - /// Guenther Grau - ///
- public sealed class Detector - { - private static readonly int[] INDEXES_START_PATTERN = {0, 4, 1, 5}; - private static readonly int[] INDEXES_STOP_PATTERN = {6, 2, 7, 3}; - private const int INTEGER_MATH_SHIFT = 8; - private const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT; - private const int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR*0.42f); - private const int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR*0.8f); - - - /// - /// B S B S B S B S Bar/Space pattern - /// 11111111 0 1 0 1 0 1 000. - /// - private static readonly int[] START_PATTERN = {8, 1, 1, 1, 1, 1, 1, 3}; - - /// - /// 1111111 0 1 000 1 0 1 00 1 - /// - private static readonly int[] STOP_PATTERN = {7, 1, 1, 3, 1, 1, 1, 2, 1}; - - private const int MAX_PIXEL_DRIFT = 3; - private const int MAX_PATTERN_DRIFT = 5; - - /// - /// if we set the value too low, then we don't detect the correct height of the bar if the start patterns are damaged. - /// if we set the value too high, then we might detect the start pattern from a neighbor barcode. - /// - private const int SKIPPED_ROW_COUNT_MAX = 25; - - /// - /// A PDF471 barcode should have at least 3 rows, with each row being >= 3 times the module width. Therefore it should be at least - /// 9 pixels tall. To be conservative, we use about half the size to ensure we don't miss it. - /// - private const int ROW_STEP = 5; - - private const int BARCODE_MIN_HEIGHT = 10; - - /// - ///

Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.

- ///
- /// barcode image to decode - /// optional hints to detector - /// if true, then the image is searched for multiple codes. If false, then at most one code will be found and returned - /// - /// encapsulating results of detecting a PDF417 code - /// - public static PDF417DetectorResult detect(BinaryBitmap image, IDictionary hints, bool multiple) - { - // TODO detection improvement, tryHarder could try several different luminance thresholds/blackpoints or even - // different binarizers (SF: or different Skipped Row Counts/Steps?) - //boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - - BitMatrix bitMatrix = image.BlackMatrix; - if (bitMatrix == null) - return null; - - List barcodeCoordinates = detect(multiple, bitMatrix); - if (barcodeCoordinates == null || - barcodeCoordinates.Count == 0) - { - bitMatrix = (BitMatrix) bitMatrix.Clone(); - bitMatrix.rotate180(); - barcodeCoordinates = detect(multiple, bitMatrix); - } - return new PDF417DetectorResult(bitMatrix, barcodeCoordinates); - } - - /// - /// Detects PDF417 codes in an image. Only checks 0 degree rotation (so rotate the matrix and check again outside of this method) - /// - /// multiple if true, then the image is searched for multiple codes. If false, then at most one code will be found and returned. - /// bit matrix to detect barcodes in. - /// List of ResultPoint arrays containing the coordinates of found barcodes - private static List detect(bool multiple, BitMatrix bitMatrix) - { - List barcodeCoordinates = new List(); - int row = 0; - int column = 0; - bool foundBarcodeInRow = false; - while (row < bitMatrix.Height) - { - ResultPoint[] vertices = findVertices(bitMatrix, row, column); - - if (vertices[0] == null && vertices[3] == null) - { - if (!foundBarcodeInRow) - { - // we didn't find any barcode so that's the end of searching - break; - } - // we didn't find a barcode starting at the given column and row. Try again from the first column and slightly - // below the lowest barcode we found so far. - foundBarcodeInRow = false; - column = 0; - foreach (ResultPoint[] barcodeCoordinate in barcodeCoordinates) - { - if (barcodeCoordinate[1] != null) - { - row = (int) Math.Max(row, barcodeCoordinate[1].Y); - } - if (barcodeCoordinate[3] != null) - { - row = Math.Max(row, (int) barcodeCoordinate[3].Y); - } - } - row += ROW_STEP; - continue; - } - foundBarcodeInRow = true; - barcodeCoordinates.Add(vertices); - if (!multiple) - { - break; - } - // if we didn't find a right row indicator column, then continue the search for the next barcode after the - // start pattern of the barcode just found. - if (vertices[2] != null) - { - column = (int) vertices[2].X; - row = (int) vertices[2].Y; - } - else - { - column = (int) vertices[4].X; - row = (int) vertices[4].Y; - } - } - return barcodeCoordinates; - } - - /// - /// Locate the vertices and the codewords area of a black blob using the Start and Stop patterns as locators. - /// - /// Matrix. - /// Start row. - /// Start column. - /// an array containing the vertices: - /// vertices[0] x, y top left barcode - /// vertices[1] x, y bottom left barcode - /// vertices[2] x, y top right barcode - /// vertices[3] x, y bottom right barcode - /// vertices[4] x, y top left codeword area - /// vertices[5] x, y bottom left codeword area - /// vertices[6] x, y top right codeword area - /// vertices[7] x, y bottom right codeword area - /// - private static ResultPoint[] findVertices(BitMatrix matrix, int startRow, int startColumn) - { - int height = matrix.Height; - int width = matrix.Width; - - ResultPoint[] result = new ResultPoint[8]; - copyToResult(result, findRowsWithPattern(matrix, height, width, startRow, startColumn, START_PATTERN), - INDEXES_START_PATTERN); - - if (result[4] != null) - { - startColumn = (int) result[4].X; - startRow = (int) result[4].Y; - } - copyToResult(result, findRowsWithPattern(matrix, height, width, startRow, startColumn, STOP_PATTERN), - INDEXES_STOP_PATTERN); - return result; - } - - /// - /// Copies the temp data to the final result - /// - /// Result. - /// Temp result. - /// Destination indexes. - private static void copyToResult(ResultPoint[] result, ResultPoint[] tmpResult, int[] destinationIndexes) - { - for (int i = 0; i < destinationIndexes.Length; i++) - { - result[destinationIndexes[i]] = tmpResult[i]; - } - } - - /// - /// Finds the rows with the given pattern. - /// - /// The rows with pattern. - /// Matrix. - /// Height. - /// Width. - /// Start row. - /// Start column. - /// Pattern. - private static ResultPoint[] findRowsWithPattern( - BitMatrix matrix, - int height, - int width, - int startRow, - int startColumn, - int[] pattern) - { - ResultPoint[] result = new ResultPoint[4]; - bool found = false; - int[] counters = new int[pattern.Length]; - for (; startRow < height; startRow += ROW_STEP) - { - int[] loc = findGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters); - if (loc != null) - { - while (startRow > 0) - { - int[] previousRowLoc = findGuardPattern(matrix, startColumn, --startRow, width, false, pattern, counters); - if (previousRowLoc != null) - { - loc = previousRowLoc; - } - else - { - startRow++; - break; - } - } - result[0] = new ResultPoint(loc[0], startRow); - result[1] = new ResultPoint(loc[1], startRow); - found = true; - break; - } - } - int stopRow = startRow + 1; - // Last row of the current symbol that contains pattern - if (found) - { - int skippedRowCount = 0; - int[] previousRowLoc = {(int) result[0].X, (int) result[1].X}; - for (; stopRow < height; stopRow++) - { - int[] loc = findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters); - // a found pattern is only considered to belong to the same barcode if the start and end positions - // don't differ too much. Pattern drift should be not bigger than two for consecutive rows. With - // a higher number of skipped rows drift could be larger. To keep it simple for now, we allow a slightly - // larger drift and don't check for skipped rows. - if (loc != null && - Math.Abs(previousRowLoc[0] - loc[0]) < MAX_PATTERN_DRIFT && - Math.Abs(previousRowLoc[1] - loc[1]) < MAX_PATTERN_DRIFT) - { - previousRowLoc = loc; - skippedRowCount = 0; - } - else - { - if (skippedRowCount > SKIPPED_ROW_COUNT_MAX) - { - break; - } - else - { - skippedRowCount++; - } - } - } - stopRow -= skippedRowCount + 1; - result[2] = new ResultPoint(previousRowLoc[0], stopRow); - result[3] = new ResultPoint(previousRowLoc[1], stopRow); - } - if (stopRow - startRow < BARCODE_MIN_HEIGHT) - { - for (int i = 0; i < result.Length; i++) - { - result[i] = null; - } - } - return result; - } - - /// - /// Finds the guard pattern. Uses System.Linq.Enumerable.Repeat to fill in counters. This might be a performance issue? - /// - /// start/end horizontal offset of guard pattern, as an array of two ints. - /// matrix row of black/white values to search - /// column x position to start search. - /// row y position to start search. - /// width the number of pixels to search on this row. - /// If set to true search the white patterns first. - /// pattern of counts of number of black and white pixels that are being searched for as a pattern. - /// counters array of counters, as long as pattern, to re-use . - private static int[] findGuardPattern( - BitMatrix matrix, - int column, - int row, - int width, - bool whiteFirst, - int[] pattern, - int[] counters) - { - SupportClass.Fill(counters, 0); - int patternLength = pattern.Length; - bool isWhite = whiteFirst; - int patternStart = column; - int pixelDrift = 0; - - // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels - while (matrix[patternStart, row] && patternStart > 0 && pixelDrift++ < MAX_PIXEL_DRIFT) - { - patternStart--; - } - int x = patternStart; - int counterPosition = 0; - for (; x < width; x++) - { - bool pixel = matrix[x, row]; - if (pixel ^ isWhite) - { - counters[counterPosition]++; - } - else - { - if (counterPosition == patternLength - 1) - { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) - { - return new int[] {patternStart, x}; - } - patternStart += counters[0] + counters[1]; - Array.Copy(counters, 2, counters, 0, patternLength - 2); - counters[patternLength - 2] = 0; - counters[patternLength - 1] = 0; - counterPosition--; - } - else - { - counterPosition++; - } - counters[counterPosition] = 1; - isWhite = !isWhite; - } - } - if (counterPosition == patternLength - 1) - { - if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) - { - return new int[] {patternStart, x - 1}; - } - } - return null; - } - - /// - /// Determines how closely a set of observed counts of runs of black/white. - /// values matches a given target pattern. This is reported as the ratio of - /// the total variance from the expected pattern proportions across all - /// pattern elements, to the length of the pattern. - /// - /// - /// ratio of total variance between counters and pattern compared to - /// total pattern size, where the ratio has been multiplied by 256. - /// So, 0 means no variance (perfect match); 256 means the total - /// variance between counters and patterns equals the pattern length, - /// higher values mean even more variance - /// - /// observed counters. - /// expected pattern. - /// The most any counter can differ before we give up. - private static int patternMatchVariance(int[] counters, int[] pattern, int maxIndividualVariance) - { - int numCounters = counters.Length; - int total = 0; - int patternLength = 0; - for (int i = 0; i < numCounters; i++) - { - total += counters[i]; - patternLength += pattern[i]; - } - if (total < patternLength) - { - // If we don't even have one pixel per unit of bar width, assume this - // is too small to reliably match, so fail: - return int.MaxValue; - } - // We're going to fake floating-point math in integers. We just need to use more bits. - // Scale up patternLength so that intermediate values below like scaledCounter will have - // more "significant digits". - int unitBarWidth = (total << INTEGER_MATH_SHIFT)/patternLength; - maxIndividualVariance = (maxIndividualVariance*unitBarWidth) >> INTEGER_MATH_SHIFT; - - int totalVariance = 0; - for (int x = 0; x < numCounters; x++) - { - int counter = counters[x] << INTEGER_MATH_SHIFT; - int scaledPattern = pattern[x]*unitBarWidth; - int variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter; - if (variance > maxIndividualVariance) - { - return int.MaxValue; - } - totalVariance += variance; - } - return totalVariance/total; - - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/detector/PDF417DetectorResult.cs b/zxing.core/xx/pdf417/detector/PDF417DetectorResult.cs deleted file mode 100644 index 53121dc..0000000 --- a/zxing.core/xx/pdf417/detector/PDF417DetectorResult.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.PDF417.Internal -{ - /// - /// PDF 417 Detector Result class. Skipped private backing stores. - /// Guenther Grau - /// - public sealed class PDF417DetectorResult - { - public BitMatrix Bits { get; private set; } - public List Points { get; private set; } - - /// - /// Initializes a new instance of the class. - /// - /// Bits. - /// Points. - public PDF417DetectorResult(BitMatrix bits, List points) - { - Bits = bits; - Points = points; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/encoder/BarcodeMatrix.cs b/zxing.core/xx/pdf417/encoder/BarcodeMatrix.cs deleted file mode 100644 index 98250f0..0000000 --- a/zxing.core/xx/pdf417/encoder/BarcodeMatrix.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2011 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.PDF417.Internal -{ - /// - /// Holds all of the information for a barcode in a format where it can be easily accessable - /// - /// Jacob Haynes - /// - internal sealed class BarcodeMatrix - { - private readonly BarcodeRow[] matrix; - private int currentRow; - private readonly int height; - private readonly int width; - - /// - /// the height of the matrix (Rows) - /// the width of the matrix (Cols) - /// - internal BarcodeMatrix(int height, int width) - { - matrix = new BarcodeRow[height]; - //Initializes the array to the correct width - for (int i = 0, matrixLength = matrix.Length; i < matrixLength; i++) - { - matrix[i] = new BarcodeRow((width + 4)*17 + 1); - } - this.width = width*17; - this.height = height; - this.currentRow = -1; - } - - internal void set(int x, int y, sbyte value) - { - matrix[y][x] = value; - } - - /* - internal void setMatrix(int x, int y, bool black) - { - set(x, y, (sbyte) (black ? 1 : 0)); - } - */ - - internal void startRow() - { - ++currentRow; - } - - internal BarcodeRow getCurrentRow() - { - return matrix[currentRow]; - } - - internal sbyte[][] getMatrix() - { - return getScaledMatrix(1, 1); - } - - /* - internal sbyte[][] getScaledMatrix(int Scale) - { - return getScaledMatrix(Scale, Scale); - } - */ - - internal sbyte[][] getScaledMatrix(int xScale, int yScale) - { - sbyte[][] matrixOut = new sbyte[height*yScale][]; - for (int idx = 0; idx < height*yScale; idx++) - matrixOut[idx] = new sbyte[width*xScale]; - int yMax = height*yScale; - for (int ii = 0; ii < yMax; ii++) - { - matrixOut[yMax - ii - 1] = matrix[ii/yScale].getScaledRow(xScale); - } - return matrixOut; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/encoder/BarcodeRow.cs b/zxing.core/xx/pdf417/encoder/BarcodeRow.cs deleted file mode 100644 index 2719eab..0000000 --- a/zxing.core/xx/pdf417/encoder/BarcodeRow.cs +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2011 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.PDF417.Internal -{ - /// - /// Jacob Haynes - /// - internal sealed class BarcodeRow - { - private readonly sbyte[] row; - //A tacker for position in the bar - private int currentLocation; - - /// - /// Creates a Barcode row of the width - /// - /// The width. - internal BarcodeRow(int width) - { - row = new sbyte[width]; - currentLocation = 0; - } - - /// - /// Sets a specific location in the bar - /// - /// The location in the bar - /// Black if true, white if false; - /// - internal sbyte this[int x] - { - get { return row[x]; } - set { row[x] = value; } - } - - /// - /// Sets a specific location in the bar - /// - /// The location in the bar - /// Black if true, white if false; - /// - internal void set(int x, bool black) - { - row[x] = (sbyte) (black ? 1 : 0); - } - - /// - /// A boolean which is true if the bar black false if it is white - /// How many spots wide the bar is. - /// - internal void addBar(bool black, int width) - { - for (int ii = 0; ii < width; ii++) - { - set(currentLocation++, black); - } - } - - /* - internal sbyte[] Row - { - get { return row; } - } - */ - - /// - /// This function scales the row - /// - /// How much you want the image to be scaled, must be greater than or equal to 1. - /// the scaled row - /// - internal sbyte[] getScaledRow(int scale) - { - var output = new sbyte[row.Length*scale]; - for (int i = 0; i < output.Length; i++) - { - output[i] = row[i/scale]; - } - return output; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/encoder/Compaction.cs b/zxing.core/xx/pdf417/encoder/Compaction.cs deleted file mode 100644 index c5f30e7..0000000 --- a/zxing.core/xx/pdf417/encoder/Compaction.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011 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.PDF417.Internal -{ - /// - /// PDF417 compaction mode - /// - public enum Compaction - { - /// - /// - /// - AUTO, - - /// - /// - /// - TEXT, - - /// - /// - /// - BYTE, - - /// - /// - /// - NUMERIC - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/encoder/Dimensions.cs b/zxing.core/xx/pdf417/encoder/Dimensions.cs deleted file mode 100644 index e9c4bfa..0000000 --- a/zxing.core/xx/pdf417/encoder/Dimensions.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2012 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace ZXing.PDF417.Internal -{ - /// - /// Data object to specify the minimum and maximum number of rows and columns for a PDF417 barcode. - /// @author qwandor@google.com (Andrew Walbran) - /// - public sealed class Dimensions - { - private readonly int minCols; - private readonly int maxCols; - private readonly int minRows; - private readonly int maxRows; - - /// - /// Initializes a new instance of the class. - /// - /// The min cols. - /// The max cols. - /// The min rows. - /// The max rows. - public Dimensions(int minCols, int maxCols, int minRows, int maxRows) - { - this.minCols = minCols; - this.maxCols = maxCols; - this.minRows = minRows; - this.maxRows = maxRows; - } - - /// - /// Gets the min cols. - /// - public int MinCols - { - get { return minCols; } - } - - /// - /// Gets the max cols. - /// - public int MaxCols - { - get { return maxCols; } - } - - /// - /// Gets the min rows. - /// - public int MinRows - { - get { return minRows; } - } - - /// - /// Gets the max rows. - /// - public int MaxRows - { - get { return maxRows; } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/encoder/PDF417.cs b/zxing.core/xx/pdf417/encoder/PDF417.cs deleted file mode 100644 index ba65a7c..0000000 --- a/zxing.core/xx/pdf417/encoder/PDF417.cs +++ /dev/null @@ -1,840 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * 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. - */ - -/* - * This file has been modified from its original form in Barcode4J. - */ - -using System; -using System.Text; - -namespace ZXing.PDF417.Internal -{ - /// - /// Top-level class for the logic part of the PDF417 implementation. - /// - internal sealed class PDF417 - { - /// - /// The start pattern (17 bits) - /// - private const int START_PATTERN = 0x1fea8; - - /// - /// The stop pattern (18 bits) - /// - private const int STOP_PATTERN = 0x3fa29; - - /// - /// The codeword table from the Annex A of ISO/IEC 15438:2001(E). - /// - private static readonly int[][] CODEWORD_TABLE = - { - new[] - { - 0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, - 0x1a8c0, 0x1d470, 0x1a860, 0x15040, 0x1a830, 0x15020, - 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0, 0x1d678, 0x1eb3e, - 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c, - 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, - 0x1af7c, 0x15e78, 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, - 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270, 0x1e93c, 0x1a460, - 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418, - 0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, - 0x1d33c, 0x14c60, 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, - 0x14ee0, 0x1a778, 0x1d3be, 0x14e70, 0x1a73c, 0x14e38, - 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0, - 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, - 0x1a230, 0x1d11c, 0x14420, 0x1a218, 0x14410, 0x14408, - 0x146c0, 0x1a370, 0x1d1bc, 0x14660, 0x1a338, 0x1d19e, - 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc, - 0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, - 0x1e85e, 0x14240, 0x1a130, 0x1d09c, 0x14220, 0x1a118, - 0x1d08e, 0x14210, 0x1a10c, 0x14208, 0x1a106, 0x14360, - 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e, - 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, - 0x1d05c, 0x14120, 0x1a098, 0x1d04e, 0x14110, 0x1a08c, - 0x14108, 0x1a086, 0x14104, 0x141b0, 0x14198, 0x1418c, - 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0, - 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, - 0x1ca38, 0x1e51e, 0x12840, 0x19430, 0x12820, 0x196e0, - 0x1cb78, 0x1e5be, 0x12cc0, 0x19670, 0x1cb3c, 0x12c60, - 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe, - 0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, - 0x12f3c, 0x12fbe, 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, - 0x1ed38, 0x1f69e, 0x1b440, 0x1da30, 0x1ed1c, 0x1b420, - 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970, - 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, - 0x1db38, 0x1ed9e, 0x16c40, 0x12420, 0x19218, 0x1c90e, - 0x16c20, 0x1b618, 0x16c10, 0x126c0, 0x19370, 0x1c9bc, - 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738, - 0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, - 0x16f70, 0x12738, 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, - 0x127bc, 0x16fbc, 0x1279e, 0x16f9e, 0x1d960, 0x1ecb8, - 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918, - 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, - 0x1c8b8, 0x1e45e, 0x1b360, 0x19130, 0x1c89c, 0x16640, - 0x12220, 0x1d99c, 0x1c88e, 0x16620, 0x12210, 0x1910c, - 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8, - 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, - 0x1918e, 0x16718, 0x1230c, 0x12306, 0x123b8, 0x191de, - 0x167b8, 0x1239c, 0x1679c, 0x1238e, 0x1678e, 0x167de, - 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e, - 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, - 0x12140, 0x190b0, 0x1c85c, 0x16340, 0x12120, 0x19098, - 0x1c84e, 0x16320, 0x1b198, 0x1d8ce, 0x16310, 0x12108, - 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc, - 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, - 0x12186, 0x16386, 0x163dc, 0x163ce, 0x1b0a0, 0x1d858, - 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088, 0x1d846, 0x1b084, - 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090, - 0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, - 0x16184, 0x12082, 0x120d8, 0x161d8, 0x161cc, 0x161c6, - 0x1d82c, 0x1d826, 0x1b042, 0x1902c, 0x12048, 0x160c8, - 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60, - 0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, - 0x11410, 0x11408, 0x116c0, 0x18b70, 0x1c5bc, 0x11660, - 0x18b38, 0x1c59e, 0x11630, 0x18b1c, 0x11618, 0x1160c, - 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc, - 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, - 0x1e69c, 0x19a20, 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, - 0x19a08, 0x1cd06, 0x18960, 0x1c4b8, 0x1e25e, 0x19b60, - 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e, - 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, - 0x11360, 0x189b8, 0x1c4de, 0x13760, 0x11330, 0x1cdde, - 0x13730, 0x19b9c, 0x1898e, 0x13718, 0x1130c, 0x1370c, - 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e, - 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, - 0x1ee98, 0x1f74e, 0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, - 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c, 0x1bb40, 0x19920, - 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10, - 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, - 0x188b0, 0x1c45c, 0x13340, 0x11120, 0x18898, 0x1c44e, - 0x17740, 0x13320, 0x19998, 0x1ccce, 0x17720, 0x1bb98, - 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708, - 0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, - 0x177b0, 0x13398, 0x199ce, 0x17798, 0x1bbce, 0x11186, - 0x13386, 0x111dc, 0x133dc, 0x111ce, 0x177dc, 0x133ce, - 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88, - 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, - 0x1b9a0, 0x19890, 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, - 0x1b988, 0x19884, 0x1b984, 0x19882, 0x1b982, 0x110a0, - 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0, - 0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, - 0x17388, 0x13184, 0x11082, 0x13182, 0x110d8, 0x1886e, - 0x131d8, 0x110cc, 0x173d8, 0x131cc, 0x110c6, 0x173cc, - 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48, - 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, - 0x19848, 0x1cc26, 0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, - 0x1b8c2, 0x11050, 0x1882c, 0x130d0, 0x11048, 0x18826, - 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042, - 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, - 0x1ee16, 0x1dc22, 0x1cc16, 0x19824, 0x19822, 0x11028, - 0x13068, 0x170e8, 0x11022, 0x13062, 0x18560, 0x10a40, - 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c, - 0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, - 0x1859c, 0x10b18, 0x1858e, 0x10b0c, 0x10b06, 0x10bb8, - 0x185de, 0x10b9c, 0x10b8e, 0x10bde, 0x18d40, 0x1c6b0, - 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08, - 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, - 0x10920, 0x1c6dc, 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, - 0x11b10, 0x10908, 0x18486, 0x11b08, 0x18d86, 0x10902, - 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98, - 0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, - 0x11bce, 0x1cea0, 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, - 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82, 0x18ca0, 0x1c658, - 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646, - 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, - 0x18458, 0x119a0, 0x10890, 0x1c66e, 0x13ba0, 0x11990, - 0x18ccc, 0x18446, 0x13b90, 0x19dcc, 0x10884, 0x13b88, - 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8, - 0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, - 0x108ee, 0x119ee, 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, - 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50, 0x1e72c, 0x1ded0, - 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42, - 0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, - 0x1bdd0, 0x19cc8, 0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, - 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850, 0x1842c, 0x118d0, - 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0, - 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, - 0x17bc4, 0x1086c, 0x118ec, 0x10866, 0x139ec, 0x118e6, - 0x17bec, 0x139e6, 0x17be6, 0x1ef28, 0x1f796, 0x1ef24, - 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64, - 0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, - 0x1bce8, 0x19c64, 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, - 0x10828, 0x18416, 0x11868, 0x18c36, 0x138e8, 0x11864, - 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2, - 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, - 0x19c34, 0x1bc74, 0x1bc72, 0x11834, 0x13874, 0x178f4, - 0x178f2, 0x10540, 0x10520, 0x18298, 0x10510, 0x10508, - 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc, - 0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, - 0x18684, 0x18682, 0x104a0, 0x18258, 0x10da0, 0x186d8, - 0x1824c, 0x10d90, 0x186cc, 0x10d88, 0x186c6, 0x10d84, - 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee, - 0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, - 0x1c748, 0x1c744, 0x1c742, 0x18650, 0x18ed0, 0x1c76c, - 0x1c326, 0x18ec8, 0x1c766, 0x18ec4, 0x18642, 0x18ec2, - 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8, - 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, - 0x1046c, 0x10cec, 0x10466, 0x11dec, 0x10ce6, 0x11de6, - 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728, 0x1cf68, 0x1e7b6, - 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68, - 0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, - 0x19ee2, 0x10428, 0x18216, 0x10c68, 0x18636, 0x11ce8, - 0x10c64, 0x10422, 0x13de8, 0x11ce4, 0x10c62, 0x13de4, - 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4, - 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, - 0x1cf34, 0x1c712, 0x1df74, 0x1cf32, 0x1df72, 0x18614, - 0x18e34, 0x18612, 0x19e74, 0x18e32, 0x1bef4 - }, - new[] - { - 0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, - 0x1f518, 0x1fa8e, 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, - 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade, 0x1d640, 0x1eb30, - 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c, - 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, - 0x1ae40, 0x1d730, 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, - 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706, 0x1ae04, 0x1af60, - 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20, - 0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, - 0x15f60, 0x1afb8, 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, - 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde, 0x15f9c, 0x15f8e, - 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e, - 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, - 0x1d340, 0x1e9b0, 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, - 0x1d310, 0x1e98c, 0x1d308, 0x1e986, 0x1d304, 0x1d302, - 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce, - 0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, - 0x14f40, 0x1a7b0, 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, - 0x14f10, 0x1a78c, 0x14f08, 0x1a786, 0x14f04, 0x14fb0, - 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc, - 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, - 0x1e888, 0x1f446, 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, - 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188, 0x1e8c6, 0x1d184, - 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc, - 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, - 0x1d1ee, 0x14790, 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, - 0x14782, 0x147d8, 0x1a3ee, 0x147cc, 0x147c6, 0x147ee, - 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842, - 0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, - 0x1a1d0, 0x1d0ec, 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, - 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6, 0x143c4, 0x143c2, - 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822, - 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, - 0x1a0e4, 0x1a0e2, 0x141e8, 0x1a0f6, 0x141e4, 0x141e2, - 0x1e814, 0x1e812, 0x1d034, 0x1d032, 0x1a074, 0x1a072, - 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e, - 0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, - 0x1cb40, 0x1e5b0, 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, - 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586, 0x1cb04, 0x1cb02, - 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce, - 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, - 0x12f40, 0x197b0, 0x1cbdc, 0x12f20, 0x19798, 0x1cbce, - 0x12f10, 0x1978c, 0x12f08, 0x19786, 0x12f04, 0x12fb0, - 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc, - 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, - 0x169f8, 0x1f688, 0x1fb46, 0x168fc, 0x1f684, 0x1f682, - 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0, 0x1e490, 0x1fb6e, - 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84, - 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, - 0x1c990, 0x1e4cc, 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, - 0x1c984, 0x1db84, 0x1c982, 0x1db82, 0x193a0, 0x1c9d8, - 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc, - 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, - 0x127a0, 0x193d8, 0x1c9ee, 0x16fa0, 0x12790, 0x193cc, - 0x16f90, 0x1b7cc, 0x193c6, 0x16f88, 0x12784, 0x16f84, - 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc, - 0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, - 0x1f648, 0x1fb26, 0x164fc, 0x1f644, 0x1647e, 0x1f642, - 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448, 0x1f226, 0x1ecc8, - 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c, - 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, - 0x1c8c2, 0x1d9c2, 0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, - 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4, 0x191c2, 0x1b3c2, - 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8, - 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, - 0x123e6, 0x167e6, 0x1f628, 0x1fb16, 0x162fc, 0x1f624, - 0x1627e, 0x1f622, 0x1e428, 0x1f216, 0x1ec68, 0x1f636, - 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8, - 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, - 0x1b1e8, 0x1d8f6, 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, - 0x190f6, 0x163e8, 0x121e4, 0x163e4, 0x121e2, 0x163e2, - 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414, - 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, - 0x1d872, 0x19074, 0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, - 0x161f4, 0x120f2, 0x161f2, 0x1f60a, 0x1e40a, 0x1ec1a, - 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158, - 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, - 0x1e282, 0x1c5a0, 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, - 0x1c588, 0x1e2c6, 0x1c584, 0x1c582, 0x18ba0, 0x1c5d8, - 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84, - 0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, - 0x11788, 0x18bc6, 0x11784, 0x11782, 0x117d8, 0x18bee, - 0x117cc, 0x117c6, 0x117ee, 0x1f350, 0x1f9ac, 0x135f8, - 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342, - 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, - 0x1f366, 0x1e6c4, 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, - 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8, 0x1e6e6, 0x1cdc4, - 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8, - 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, - 0x113d0, 0x189ec, 0x137d0, 0x113c8, 0x189e6, 0x137c8, - 0x19be6, 0x137c4, 0x113c2, 0x137c2, 0x113ec, 0x137ec, - 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4, - 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, - 0x1f996, 0x132fc, 0x1f768, 0x1fbb6, 0x176fc, 0x1327e, - 0x1f764, 0x1f322, 0x1767e, 0x1f762, 0x1e228, 0x1f116, - 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4, - 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, - 0x1dde8, 0x1cce4, 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, - 0x188e8, 0x1c476, 0x199e8, 0x188e4, 0x1bbe8, 0x199e4, - 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6, - 0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, - 0x133e2, 0x177e2, 0x111f6, 0x133f6, 0x1fb94, 0x172f8, - 0x1b97e, 0x1fb92, 0x1727c, 0x1723e, 0x1f314, 0x1317e, - 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634, - 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, - 0x1c432, 0x1dcf4, 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, - 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2, 0x110f4, 0x131f4, - 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c, - 0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, - 0x1c41a, 0x1cc3a, 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, - 0x1107a, 0x130fa, 0x171fa, 0x170be, 0x1e150, 0x1f0ac, - 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c, - 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, - 0x185c8, 0x1c2e6, 0x185c4, 0x185c2, 0x10bd0, 0x185ec, - 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2, 0x10bec, 0x10be6, - 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2, - 0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, - 0x1e362, 0x1c268, 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, - 0x1c262, 0x1c6e2, 0x184e8, 0x1c276, 0x18de8, 0x184e4, - 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8, - 0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, - 0x1f9d4, 0x13af8, 0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, - 0x1f194, 0x1197e, 0x1f3b4, 0x1f192, 0x13b7e, 0x1f3b2, - 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772, - 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, - 0x18474, 0x18cf4, 0x18472, 0x19df4, 0x18cf2, 0x19df2, - 0x108f4, 0x119f4, 0x108f2, 0x13bf4, 0x119f2, 0x13bf2, - 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e, - 0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, - 0x1f18a, 0x1f39a, 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, - 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a, 0x1defa, 0x1843a, - 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa, - 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, - 0x178bc, 0x1789e, 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, - 0x1c168, 0x1e0b6, 0x1c164, 0x1c162, 0x182e8, 0x1c176, - 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2, - 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, - 0x1e092, 0x1e1b2, 0x1c134, 0x1c374, 0x1c132, 0x1c372, - 0x18274, 0x186f4, 0x18272, 0x186f2, 0x104f4, 0x10df4, - 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca, - 0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, - 0x1c77a, 0x1823a, 0x1867a, 0x18efa, 0x1047a, 0x10cfa, - 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c, 0x13d1e, 0x11cbe, - 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c, - 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, - 0x1be5e, 0x17c9c, 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, - 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2, 0x18174, 0x18172, - 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a, - 0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, - 0x13eb8, 0x19f5e, 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, - 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e, 0x17e8c, 0x17e86, - 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e, - 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, - 0x10f5e, 0x11f5c, 0x11f4e, 0x13f58, 0x19fae, 0x13f4c, - 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c, 0x13f26 - }, - new[] - { - 0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, - 0x1a8f8, 0x1d47e, 0x150f0, 0x1a87c, 0x15078, 0x1fad0, - 0x15be0, 0x1adf8, 0x1fac8, 0x159f0, 0x1acfc, 0x1fac4, - 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec, - 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, - 0x1f5c2, 0x1ebd0, 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, - 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8, 0x1ebe6, 0x1d7c4, - 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4, - 0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, - 0x148f0, 0x1a47c, 0x14878, 0x1a43e, 0x1483c, 0x1fa68, - 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8, 0x1a67e, 0x1fa62, - 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4, - 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, - 0x1d3e8, 0x1e9f6, 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, - 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8, 0x1d17e, 0x144f0, - 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34, - 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, - 0x1477e, 0x1f472, 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, - 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c, 0x14278, 0x1a13e, - 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a, - 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, - 0x141be, 0x140bc, 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, - 0x129e0, 0x194f8, 0x1ca7e, 0x128f0, 0x1947c, 0x12878, - 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964, - 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, - 0x1f976, 0x12efc, 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, - 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8, 0x1e5f6, 0x1cbe4, - 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0, - 0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, - 0x1b478, 0x1da3e, 0x16870, 0x1b43c, 0x16838, 0x1b41e, - 0x1681c, 0x125e0, 0x192f8, 0x1c97e, 0x16de0, 0x124f0, - 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c, - 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, - 0x1fb74, 0x1f932, 0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, - 0x1263e, 0x16e3e, 0x1f274, 0x1277e, 0x1f6f4, 0x1f272, - 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2, - 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, - 0x165c0, 0x1b2f0, 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, - 0x16470, 0x1b23c, 0x16438, 0x1b21e, 0x1641c, 0x1640e, - 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678, - 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, - 0x1fb3a, 0x1677c, 0x1233e, 0x1673e, 0x1f23a, 0x1f67a, - 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa, 0x191fa, 0x162e0, - 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e, - 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, - 0x1633c, 0x1211e, 0x1631e, 0x121be, 0x163be, 0x16170, - 0x1b0bc, 0x16138, 0x1b09e, 0x1611c, 0x1610e, 0x120bc, - 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c, - 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, - 0x18af8, 0x1c57e, 0x114f0, 0x18a7c, 0x11478, 0x18a3e, - 0x1143c, 0x1141e, 0x1f8b4, 0x116f8, 0x18b7e, 0x1f8b2, - 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4, - 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, - 0x19af0, 0x1cd7c, 0x134e0, 0x19a78, 0x1cd3e, 0x13470, - 0x19a3c, 0x13438, 0x19a1e, 0x1341c, 0x1340e, 0x112f0, - 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e, - 0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, - 0x1377c, 0x1133e, 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, - 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa, 0x1bae0, 0x1dd78, - 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38, - 0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, - 0x132e0, 0x19978, 0x1ccbe, 0x176e0, 0x13270, 0x1993c, - 0x17670, 0x1bb3c, 0x1991e, 0x17638, 0x1321c, 0x1761c, - 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c, - 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, - 0x111be, 0x133be, 0x177be, 0x172c0, 0x1b970, 0x1dcbc, - 0x17260, 0x1b938, 0x1dc9e, 0x17230, 0x1b91c, 0x17218, - 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370, - 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, - 0x1730e, 0x110bc, 0x131bc, 0x1109e, 0x173bc, 0x1319e, - 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e, 0x17130, 0x1b89c, - 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e, - 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, - 0x130de, 0x171de, 0x170b0, 0x1b85c, 0x17098, 0x1b84e, - 0x1708c, 0x17086, 0x1305c, 0x170dc, 0x1304e, 0x170ce, - 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e, - 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, - 0x10a3c, 0x10a1e, 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, - 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78, 0x1c6be, 0x11a70, - 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978, - 0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, - 0x109be, 0x11bbe, 0x13ac0, 0x19d70, 0x1cebc, 0x13a60, - 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c, 0x13a18, 0x19d0e, - 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938, - 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, - 0x108bc, 0x119bc, 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, - 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40, 0x1bd30, 0x1de9c, - 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08, - 0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, - 0x13930, 0x19c9c, 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, - 0x1390c, 0x17b0c, 0x13906, 0x17b06, 0x118b8, 0x18c5e, - 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c, - 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, - 0x17940, 0x1bcb0, 0x1de5c, 0x17920, 0x1bc98, 0x1de4e, - 0x17910, 0x1bc8c, 0x17908, 0x1bc86, 0x17904, 0x17902, - 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998, - 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, - 0x1184e, 0x179dc, 0x138ce, 0x179ce, 0x178a0, 0x1bc58, - 0x1de2e, 0x17890, 0x1bc4c, 0x17888, 0x1bc46, 0x17884, - 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc, - 0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, - 0x1bc2c, 0x17848, 0x1bc26, 0x17844, 0x17842, 0x1382c, - 0x1786c, 0x13826, 0x17866, 0x17828, 0x1bc16, 0x17824, - 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c, - 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, - 0x10d1c, 0x10d0e, 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, - 0x11d60, 0x18eb8, 0x1c75e, 0x11d30, 0x18e9c, 0x11d18, - 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8, - 0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, - 0x11dde, 0x13d40, 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, - 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08, 0x19e86, 0x13d04, - 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e, - 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, - 0x11cdc, 0x10c4e, 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, - 0x1df58, 0x1efae, 0x1be90, 0x1df4c, 0x1be88, 0x1df46, - 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0, - 0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, - 0x13c84, 0x17d84, 0x13c82, 0x17d82, 0x11c58, 0x18e2e, - 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc, 0x11c46, 0x17dcc, - 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee, - 0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, - 0x13c50, 0x19e2c, 0x17cd0, 0x13c48, 0x19e26, 0x17cc8, - 0x1be66, 0x17cc4, 0x13c42, 0x17cc2, 0x11c2c, 0x13c6c, - 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16, - 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, - 0x17c64, 0x13c22, 0x17c62, 0x11c16, 0x13c36, 0x17c76, - 0x1be14, 0x1be12, 0x13c14, 0x17c34, 0x13c12, 0x17c32, - 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e, - 0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, - 0x10e8c, 0x10e86, 0x1065c, 0x10edc, 0x1064e, 0x10ece, - 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90, 0x18f4c, 0x11e88, - 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8, - 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, - 0x11eee, 0x19f50, 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, - 0x19f42, 0x11e50, 0x18f2c, 0x13ed0, 0x19f6c, 0x18f26, - 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c, - 0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, - 0x1efd6, 0x1dfa4, 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, - 0x19f24, 0x1bf64, 0x19f22, 0x1bf62, 0x11e28, 0x18f16, - 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4, - 0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, - 0x1df94, 0x1df92, 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, - 0x11e14, 0x13e34, 0x11e12, 0x17e74, 0x13e32, 0x17e72, - 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a, - 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, - 0x1032e, 0x1076e, 0x10f50, 0x187ac, 0x10f48, 0x187a6, - 0x10f44, 0x10f42, 0x1072c, 0x10f6c, 0x10726, 0x10f66, - 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796, - 0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, - 0x10f36, 0x11f76, 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, - 0x18f92, 0x19fb2, 0x10f14, 0x11f34, 0x10f12, 0x13f74, - 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a, - 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, - 0x107a4, 0x107a2, 0x10396, 0x107b6, 0x187d4, 0x187d2, - 0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea - } - }; - - private const float PREFERRED_RATIO = 3.0f; - private const float DEFAULT_MODULE_WIDTH = 0.357f; //1px in mm - private const float HEIGHT = 2.0f; //mm - - private BarcodeMatrix barcodeMatrix; - private bool compact; - private Compaction compaction; - private Encoding encoding; - private bool disableEci; - private int minCols; - private int maxCols; - private int maxRows; - private int minRows; - - internal PDF417() - : this(false) - { - } - - internal PDF417(bool compact) - { - this.compact = compact; - compaction = Compaction.AUTO; - encoding = null; // use default - disableEci = false; - minCols = 2; - maxCols = 30; - maxRows = 30; - minRows = 2; - } - - internal BarcodeMatrix BarcodeMatrix - { - get { return barcodeMatrix; } - } - - /// - /// Calculates the necessary number of rows as described in annex Q of ISO/IEC 15438:2001(E). - /// - /// the number of source codewords prior to the additional of the Symbol Length - /// Descriptor and any pad codewords - /// the number of error correction codewords - /// the number of columns in the symbol in the data region (excluding start, stop and - /// row indicator codewords) - /// the number of rows in the symbol (r) - private static int calculateNumberOfRows(int m, int k, int c) - { - int r = ((m + 1 + k)/c) + 1; - if (c*r >= (m + 1 + k + c)) - { - r--; - } - return r; - } - - /// - /// Calculates the number of pad codewords as described in 4.9.2 of ISO/IEC 15438:2001(E). - /// - /// the number of source codewords prior to the additional of the Symbol Length - /// Descriptor and any pad codewords - /// the number of error correction codewords - /// the number of columns in the symbol in the data region (excluding start, stop and - /// row indicator codewords) - /// the number of rows in the symbol - /// the number of pad codewords - private static int getNumberOfPadCodewords(int m, int k, int c, int r) - { - int n = c*r - k; - return n > m + 1 ? n - m - 1 : 0; - } - - private static void encodeChar(int pattern, int len, BarcodeRow logic) - { - int map = 1 << len - 1; - bool last = (pattern & map) != 0; //Initialize to inverse of first bit - int width = 0; - for (int i = 0; i < len; i++) - { - bool black = (pattern & map) != 0; - if (last == black) - { - width++; - } - else - { - logic.addBar(last, width); - - last = black; - width = 1; - } - map >>= 1; - } - logic.addBar(last, width); - } - - private void encodeLowLevel(String fullCodewords, - int c, - int r, - int errorCorrectionLevel, - BarcodeMatrix logic) - { - - int idx = 0; - for (int y = 0; y < r; y++) - { - int cluster = y%3; - logic.startRow(); - encodeChar(START_PATTERN, 17, logic.getCurrentRow()); - - int left; - int right; - if (cluster == 0) - { - left = (30*(y/3)) + ((r - 1)/3); - right = (30*(y/3)) + (c - 1); - } - else if (cluster == 1) - { - left = (30*(y/3)) + (errorCorrectionLevel*3) + ((r - 1)%3); - right = (30*(y/3)) + ((r - 1)/3); - } - else - { - left = (30*(y/3)) + (c - 1); - right = (30*(y/3)) + (errorCorrectionLevel*3) + ((r - 1)%3); - } - - int pattern = CODEWORD_TABLE[cluster][left]; - encodeChar(pattern, 17, logic.getCurrentRow()); - - for (int x = 0; x < c; x++) - { - pattern = CODEWORD_TABLE[cluster][fullCodewords[idx]]; - encodeChar(pattern, 17, logic.getCurrentRow()); - idx++; - } - - if (compact) - { - encodeChar(STOP_PATTERN, 1, logic.getCurrentRow()); // encodes stop line for compact pdf417 - } - else - { - pattern = CODEWORD_TABLE[cluster][right]; - encodeChar(pattern, 17, logic.getCurrentRow()); - - encodeChar(STOP_PATTERN, 18, logic.getCurrentRow()); - } - } - } - - /// - /// Generates the barcode logic. - /// - /// the message to encode - /// PDF417 error correction level to use - internal void generateBarcodeLogic(String msg, int errorCorrectionLevel) - { - - //1. step: High-level encoding - int errorCorrectionCodeWords = PDF417ErrorCorrection.getErrorCorrectionCodewordCount(errorCorrectionLevel); - String highLevel = PDF417HighLevelEncoder.encodeHighLevel(msg, compaction, encoding, disableEci); - int sourceCodeWords = highLevel.Length; - - int[] dimension = determineDimensions(sourceCodeWords, errorCorrectionCodeWords); - - int cols = dimension[0]; - int rows = dimension[1]; - - int pad = getNumberOfPadCodewords(sourceCodeWords, errorCorrectionCodeWords, cols, rows); - - //2. step: construct data codewords - if (sourceCodeWords + errorCorrectionCodeWords + 1 > 929) - { - // +1 for symbol length CW - throw new WriterException( - "Encoded message contains to many code words, message to big (" + msg.Length + " bytes)"); - } - int n = sourceCodeWords + pad + 1; - StringBuilder sb = new StringBuilder(n); - sb.Append((char) n); - sb.Append(highLevel); - for (int i = 0; i < pad; i++) - { - sb.Append((char) 900); //PAD characters - } - String dataCodewords = sb.ToString(); - - //3. step: Error correction - String ec = PDF417ErrorCorrection.generateErrorCorrection(dataCodewords, errorCorrectionLevel); - String fullCodewords = dataCodewords + ec; - - //4. step: low-level encoding - barcodeMatrix = new BarcodeMatrix(rows, cols); - encodeLowLevel(fullCodewords, cols, rows, errorCorrectionLevel, barcodeMatrix); - } - - /// - /// Determine optimal nr of columns and rows for the specified number of - /// codewords. - /// - /// number of code words - /// number of error correction code words - /// dimension object containing cols as width and rows as height - private int[] determineDimensions(int sourceCodeWords, int errorCorrectionCodeWords) - { - float ratio = 0.0f; - int[] dimension = null; - - for (int cols = minCols; cols <= maxCols; cols++) - { - - int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, cols); - - if (rows < minRows) - { - break; - } - - if (rows > maxRows) - { - continue; - } - - float newRatio = ((17*cols + 69)*DEFAULT_MODULE_WIDTH)/(rows*HEIGHT); - - // ignore if previous ratio is closer to preferred ratio - if (dimension != null && Math.Abs(newRatio - PREFERRED_RATIO) > Math.Abs(ratio - PREFERRED_RATIO)) - { - continue; - } - - ratio = newRatio; - dimension = new int[] {cols, rows}; - } - - // Handle case when min values were larger than necessary - if (dimension == null) - { - int rows = calculateNumberOfRows(sourceCodeWords, errorCorrectionCodeWords, minCols); - if (rows < minRows) - { - dimension = new int[] {minCols, minRows}; - } - } - - if (dimension == null) - { - throw new WriterException("Unable to fit message in columns"); - } - - return dimension; - } - - /// - /// Sets max/min row/col values - /// - /// maximum allowed columns - /// minimum allowed columns - /// maximum allowed rows - /// minimum allowed rows - internal void setDimensions(int maxCols, int minCols, int maxRows, int minRows) - { - this.maxCols = maxCols; - this.minCols = minCols; - this.maxRows = maxRows; - this.minRows = minRows; - } - - /// - /// Sets compaction to values stored in enum - /// - /// compaction mode to use - internal void setCompaction(Compaction compaction) - { - this.compaction = compaction; - } - - /// - /// Sets compact to be true or false - /// - /// if true, enables compaction - internal void setCompact(bool compact) - { - this.compact = compact; - } - - /// - /// Sets output encoding. - /// - /// sets character encoding to use - internal void setEncoding(String encodingname) - { -#if WindowsCE - try - { - this.encoding = Encoding.GetEncoding(encodingname); - } - catch (PlatformNotSupportedException) - { - // WindowsCE doesn't support all encodings. But it is device depended. - // So we try here the some different ones - this.encoding = Encoding.GetEncoding(1252); - } -#else - this.encoding = Encoding.GetEncoding(encodingname); -#endif - } - - /// - /// Sets the disable eci. - /// - /// if set to true don't add an ECI segment for different encodings than default. - internal void setDisableEci(bool disabled) - { - this.disableEci = disabled; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/encoder/PDF417EncodingOptions.cs b/zxing.core/xx/pdf417/encoder/PDF417EncodingOptions.cs deleted file mode 100644 index 0101d2b..0000000 --- a/zxing.core/xx/pdf417/encoder/PDF417EncodingOptions.cs +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 ZXing.Common; -using ZXing.PDF417.Internal; - -namespace ZXing.PDF417 -{ - /// - /// The class holds the available options for the - /// - public class PDF417EncodingOptions : EncodingOptions - { - /// - /// Specifies whether to use compact mode for PDF417 (type ). - /// - public bool Compact - { - get - { - if (Hints.ContainsKey(EncodeHintType.PDF417_COMPACT)) - { - return (bool) Hints[EncodeHintType.PDF417_COMPACT]; - } - return false; - } - set { Hints[EncodeHintType.PDF417_COMPACT] = value; } - } - - /// - /// Specifies what compaction mode to use for PDF417 (type - /// ). - /// - public Compaction Compaction - { - get - { - if (Hints.ContainsKey(EncodeHintType.PDF417_COMPACTION)) - { - return (Compaction) Hints[EncodeHintType.PDF417_COMPACTION]; - } - return Compaction.AUTO; - } - set { Hints[EncodeHintType.PDF417_COMPACTION] = value; } - } - - /// - /// Specifies the minimum and maximum number of rows and columns for PDF417 (type - /// ). - /// - public Dimensions Dimensions - { - get - { - if (Hints.ContainsKey(EncodeHintType.PDF417_DIMENSIONS)) - { - return (Dimensions) Hints[EncodeHintType.PDF417_DIMENSIONS]; - } - return null; - } - set { Hints[EncodeHintType.PDF417_DIMENSIONS] = value; } - } - - /// - /// Specifies what degree of error correction to use - /// - public PDF417ErrorCorrectionLevel ErrorCorrection - { - get - { - if (Hints.ContainsKey(EncodeHintType.ERROR_CORRECTION)) - { - var value = Hints[EncodeHintType.ERROR_CORRECTION]; - if (value is PDF417ErrorCorrectionLevel) - { - return (PDF417ErrorCorrectionLevel)value; - } - if (value is int) - { - return (PDF417ErrorCorrectionLevel)Enum.Parse(typeof(PDF417ErrorCorrectionLevel), value.ToString(), true); - } - } - return PDF417ErrorCorrectionLevel.L2; - } - set { Hints[EncodeHintType.ERROR_CORRECTION] = value; } - } - - /// - /// Specifies what character encoding to use where applicable (type {@link String}) - /// - public string CharacterSet - { - get - { - if (Hints.ContainsKey(EncodeHintType.CHARACTER_SET)) - { - return (string)Hints[EncodeHintType.CHARACTER_SET]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.CHARACTER_SET)) - Hints.Remove(EncodeHintType.CHARACTER_SET); - } - else - { - Hints[EncodeHintType.CHARACTER_SET] = value; - } - } - } - - /// - /// Explicitly disables ECI segment when generating PDF417 Code - /// That is against the specification but some - /// readers have problems if the charset is switched from - /// CP437 (default) to UTF-8 with the necessary ECI segment. - /// If you set the property to true you can use different encodings - /// and the ECI segment is omitted. - /// - public bool DisableECI - { - get - { - if (Hints.ContainsKey(EncodeHintType.DISABLE_ECI)) - { - return (bool)Hints[EncodeHintType.DISABLE_ECI]; - } - return false; - } - set - { - Hints[EncodeHintType.DISABLE_ECI] = value; - } - } - } -} diff --git a/zxing.core/xx/pdf417/encoder/PDF417ErrorCorrection.cs b/zxing.core/xx/pdf417/encoder/PDF417ErrorCorrection.cs deleted file mode 100644 index 1e5e212..0000000 --- a/zxing.core/xx/pdf417/encoder/PDF417ErrorCorrection.cs +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * 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. - */ - -/* - * This file has been modified from its original form in Barcode4J. - */ - -using System; - -using System.Text; - -namespace ZXing.PDF417.Internal -{ - /// - /// PDF417 error correction code following the algorithm described in ISO/IEC 15438:2001(E) in - /// chapter 4.10. - /// - internal static class PDF417ErrorCorrection - { - /// - /// Tables of coefficients for calculating error correction words - /// (see annex F, ISO/IEC 15438:2001(E)) - /// - private static readonly int[][] EC_COEFFICIENTS = - { - new[] {27, 917}, - new[] {522, 568, 723, 809}, - new[] {237, 308, 436, 284, 646, 653, 428, 379}, - new[] - { - 274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, - 42, 176, 65 - }, - new[] - { - 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, - 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, - 133, 231, 390, 685, 330, 63, 410 - }, - new[] - { - 539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, - 877, 381, 612, 723, 476, 462, 172, 430, 609, 858, 822, 543, - 376, 511, 400, 672, 762, 283, 184, 440, 35, 519, 31, 460, - 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502, 648, - 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, - 623, 264, 543 - }, - new[] - { - 521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, - 925, 749, 415, 822, 93, 217, 208, 928, 244, 583, 620, 246, - 148, 447, 631, 292, 908, 490, 704, 516, 258, 457, 907, 594, - 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569, 193, - 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, - 463, 646, 776, 171, 491, 297, 763, 156, 732, 95, 270, 447, - 90, 507, 48, 228, 821, 808, 898, 784, 663, 627, 378, 382, - 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, 157, - 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, - 587, 804, 34, 211, 330, 539, 297, 827, 865, 37, 517, 834, - 315, 550, 86, 801, 4, 108, 539 - }, - new[] - { - 524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, - 786, 138, 720, 858, 194, 311, 913, 275, 190, 375, 850, 438, - 733, 194, 280, 201, 280, 828, 757, 710, 814, 919, 89, 68, - 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137, 439, - 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, - 549, 209, 884, 315, 70, 329, 793, 490, 274, 877, 162, 749, - 812, 684, 461, 334, 376, 849, 521, 307, 291, 803, 712, 19, - 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470, 637, - 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, - 538, 906, 90, 2, 290, 743, 199, 655, 903, 329, 49, 802, - 580, 355, 588, 188, 462, 10, 134, 628, 320, 479, 130, 739, - 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234, 722, - 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, - 60, 732, 621, 895, 544, 261, 852, 655, 309, 697, 755, 756, - 60, 231, 773, 434, 421, 726, 528, 503, 118, 49, 795, 32, - 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550, 73, - 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, - 791, 893, 754, 605, 383, 228, 749, 760, 213, 54, 297, 134, - 54, 834, 299, 922, 191, 910, 532, 609, 829, 189, 20, 167, - 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173, 404, - 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, - 55, 497, 10 - }, - new[] - { - 352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, - 380, 350, 492, 197, 265, 920, 155, 914, 299, 229, 643, 294, - 871, 306, 88, 87, 193, 352, 781, 846, 75, 327, 520, 435, - 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534, 539, - 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, - 916, 552, 41, 542, 289, 122, 272, 383, 800, 485, 98, 752, - 472, 761, 107, 784, 860, 658, 741, 290, 204, 681, 407, 855, - 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, 808, - 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, - 192, 516, 258, 240, 518, 794, 395, 768, 848, 51, 610, 384, - 168, 190, 826, 328, 596, 786, 303, 570, 381, 415, 641, 156, - 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402, 40, - 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, - 92, 358, 785, 288, 357, 850, 836, 827, 736, 707, 94, 8, - 494, 114, 521, 2, 499, 851, 543, 152, 729, 771, 95, 248, - 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, 669, - 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, - 591, 452, 578, 37, 124, 298, 332, 552, 43, 427, 119, 662, - 777, 475, 850, 764, 364, 578, 911, 283, 711, 472, 420, 245, - 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408, 842, - 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, - 159, 672, 729, 624, 59, 193, 417, 158, 209, 563, 564, 343, - 693, 109, 608, 563, 365, 181, 772, 677, 310, 248, 353, 708, - 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, 618, - 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, - 247, 184, 45, 787, 680, 18, 66, 407, 369, 54, 492, 228, - 613, 830, 922, 437, 519, 644, 905, 789, 420, 305, 441, 207, - 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341, 242, - 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, - 665, 397, 808, 851, 309, 473, 795, 378, 31, 647, 915, 459, - 806, 590, 731, 425, 216, 548, 249, 321, 881, 699, 535, 673, - 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, 660, - 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, - 336, 286, 437, 375, 273, 610, 296, 183, 923, 116, 667, 751, - 353, 62, 366, 691, 379, 687, 842, 37, 357, 720, 742, 330, - 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316, 342, - 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, - 610, 46, 656, 447, 171, 616, 464, 190, 531, 297, 321, 762, - 752, 533, 175, 134, 14, 381, 433, 717, 45, 111, 20, 596, - 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780, 407, - 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, - 223, 849, 647, 63, 310, 863, 251, 366, 304, 282, 738, 675, - 410, 389, 244, 31, 121, 303, 263 - } - }; - - /// - /// Determines the number of error correction codewords for a specified error correction - /// level. - /// - /// the error correction level (0-8) - /// the number of codewords generated for error correction - internal static int getErrorCorrectionCodewordCount(int errorCorrectionLevel) - { - if (errorCorrectionLevel < 0 || errorCorrectionLevel > 8) - { - throw new ArgumentException("Error correction level must be between 0 and 8!"); - } - return 1 << (errorCorrectionLevel + 1); - } - - /// - /// Returns the recommended minimum error correction level as described in annex E of - /// ISO/IEC 15438:2001(E). - /// - /// the number of data codewords - /// the recommended minimum error correction level - internal static int getRecommendedMinimumErrorCorrectionLevel(int n) - { - if (n <= 0) - { - throw new ArgumentException("n must be > 0"); - } - if (n <= 40) - { - return 2; - } - if (n <= 160) - { - return 3; - } - if (n <= 320) - { - return 4; - } - if (n <= 863) - { - return 5; - } - throw new WriterException("No recommendation possible"); - } - - /// - /// Generates the error correction codewords according to 4.10 in ISO/IEC 15438:2001(E). - /// - /// the data codewords - /// the error correction level (0-8) - /// the String representing the error correction codewords - internal static String generateErrorCorrection(String dataCodewords, int errorCorrectionLevel) - { - int k = getErrorCorrectionCodewordCount(errorCorrectionLevel); - char[] e = new char[k]; - int sld = dataCodewords.Length; - for (int i = 0; i < sld; i++) - { - int t1 = (dataCodewords[i] + e[e.Length - 1])%929; - int t2; - int t3; - for (int j = k - 1; j >= 1; j--) - { - t2 = (t1*EC_COEFFICIENTS[errorCorrectionLevel][j])%929; - t3 = 929 - t2; - e[j] = (char) ((e[j - 1] + t3)%929); - } - t2 = (t1*EC_COEFFICIENTS[errorCorrectionLevel][0])%929; - t3 = 929 - t2; - e[0] = (char) (t3%929); - } - StringBuilder sb = new StringBuilder(k); - for (int j = k - 1; j >= 0; j--) - { - if (e[j] != 0) - { - e[j] = (char) (929 - e[j]); - } - sb.Append(e[j]); - } - return sb.ToString(); - } - } - - /// - /// defines the level of the error correction / count of error correction codewords - /// - public enum PDF417ErrorCorrectionLevel - { - L0 = 0, - L1, - L2, - L3, - L4, - L5, - L6, - L7, - L8 - } -} \ No newline at end of file diff --git a/zxing.core/xx/pdf417/encoder/PDF417HighLevelEncoder.cs b/zxing.core/xx/pdf417/encoder/PDF417HighLevelEncoder.cs deleted file mode 100644 index 023944f..0000000 --- a/zxing.core/xx/pdf417/encoder/PDF417HighLevelEncoder.cs +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Copyright 2006 Jeremias Maerki in part, and ZXing Authors in part - * - * 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. - */ - -/* - * This file has been modified from its original form in Barcode4J. - */ - -using System; -using System.Numerics; -using System.Text; - -using ZXing.Common; - -namespace ZXing.PDF417.Internal -{ - /// - /// PDF417 high-level encoder following the algorithm described in ISO/IEC 15438:2001(E) in - /// annex P. - /// - internal static class PDF417HighLevelEncoder - { - /// - /// code for Text compaction - /// - private const int TEXT_COMPACTION = 0; - - /// - /// code for Byte compaction - /// - private const int BYTE_COMPACTION = 1; - - /// - /// code for Numeric compaction - /// - private const int NUMERIC_COMPACTION = 2; - - /// - /// Text compaction submode Alpha - /// - private const int SUBMODE_ALPHA = 0; - - /// - /// Text compaction submode Lower - /// - private const int SUBMODE_LOWER = 1; - - /// - /// Text compaction submode Mixed - /// - private const int SUBMODE_MIXED = 2; - - /// - /// Text compaction submode Punctuation - /// - private const int SUBMODE_PUNCTUATION = 3; - - /// - /// mode latch to Text Compaction mode - /// - private const int LATCH_TO_TEXT = 900; - - /// - /// mode latch to Byte Compaction mode (number of characters NOT a multiple of 6) - /// - private const int LATCH_TO_BYTE_PADDED = 901; - - /// - /// mode latch to Numeric Compaction mode - /// - private const int LATCH_TO_NUMERIC = 902; - - /// - /// mode shift to Byte Compaction mode - /// - private const int SHIFT_TO_BYTE = 913; - - /// - /// mode latch to Byte Compaction mode (number of characters a multiple of 6) - /// - private const int LATCH_TO_BYTE = 924; - - /// - /// identifier for a user defined Extended Channel Interpretation (ECI) - /// - private const int ECI_USER_DEFINED = 925; - - /// - /// identifier for a general purpose ECO format - /// - private const int ECI_GENERAL_PURPOSE = 926; - - /// - /// identifier for an ECI of a character set of code page - /// - private const int ECI_CHARSET = 927; - - /// - /// Raw code table for text compaction Mixed sub-mode - /// - private static readonly sbyte[] TEXT_MIXED_RAW = - { - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58, - 35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0 - }; - - /// - /// Raw code table for text compaction: Punctuation sub-mode - /// - private static readonly sbyte[] TEXT_PUNCTUATION_RAW = - { - 59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58, - 10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0 - }; - - private static readonly sbyte[] MIXED = new sbyte[128]; - private static readonly sbyte[] PUNCTUATION = new sbyte[128]; - - internal static string DEFAULT_ENCODING_NAME = "ISO-8859-1"; - - static PDF417HighLevelEncoder() - { - //Construct inverse lookups - for (int idx = 0; idx < MIXED.Length; idx++) - MIXED[idx] = -1; - for (sbyte i = 0; i < TEXT_MIXED_RAW.Length; i++) - { - sbyte b = TEXT_MIXED_RAW[i]; - if (b > 0) - { - MIXED[b] = i; - } - } - for (int idx = 0; idx < PUNCTUATION.Length; idx++) - PUNCTUATION[idx] = -1; - for (sbyte i = 0; i < TEXT_PUNCTUATION_RAW.Length; i++) - { - sbyte b = TEXT_PUNCTUATION_RAW[i]; - if (b > 0) - { - PUNCTUATION[b] = i; - } - } - } - - /// - /// Performs high-level encoding of a PDF417 message using the algorithm described in annex P - /// of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction - /// is used. - /// - /// the message - /// compaction mode to use - /// character encoding used to encode in default or byte compaction - /// or null for default / not applicable - /// if true, don't add an ECI segment for different encodings than default - /// the encoded message (the char values range from 0 to 928) - internal static String encodeHighLevel(String msg, Compaction compaction, Encoding encoding, bool disableEci) - { - //the codewords 0..928 are encoded as Unicode characters - var sb = new StringBuilder(msg.Length); - - if (encoding != null && !disableEci && String.Compare(DEFAULT_ENCODING_NAME, encoding.WebName, StringComparison.Ordinal) != 0) - { - CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding.WebName); - if (eci != null) - { - encodingECI(eci.Value, sb); - } - } - - int len = msg.Length; - int p = 0; - int textSubMode = SUBMODE_ALPHA; - - // User selected encoding mode - byte[] bytes = null; //Fill later and only if needed - if (compaction == Compaction.TEXT) - { - encodeText(msg, p, len, sb, textSubMode); - - } - else if (compaction == Compaction.BYTE) - { - bytes = toBytes(msg, encoding); - encodeBinary(bytes, p, bytes.Length, BYTE_COMPACTION, sb); - - } - else if (compaction == Compaction.NUMERIC) - { - sb.Append((char) LATCH_TO_NUMERIC); - encodeNumeric(msg, p, len, sb); - - } - else - { - int encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1 - while (p < len) - { - int n = determineConsecutiveDigitCount(msg, p); - if (n >= 13) - { - sb.Append((char) LATCH_TO_NUMERIC); - encodingMode = NUMERIC_COMPACTION; - textSubMode = SUBMODE_ALPHA; //Reset after latch - encodeNumeric(msg, p, n, sb); - p += n; - } - else - { - int t = determineConsecutiveTextCount(msg, p); - if (t >= 5 || n == len) - { - if (encodingMode != TEXT_COMPACTION) - { - sb.Append((char) LATCH_TO_TEXT); - encodingMode = TEXT_COMPACTION; - textSubMode = SUBMODE_ALPHA; //start with submode alpha after latch - } - textSubMode = encodeText(msg, p, t, sb, textSubMode); - p += t; - } - else - { - if (bytes == null) - { - bytes = toBytes(msg, encoding); - } - int b = determineConsecutiveBinaryCount(msg, bytes, p); - if (b == 0) - { - b = 1; - } - if (b == 1 && encodingMode == TEXT_COMPACTION) - { - //Switch for one byte (instead of latch) - encodeBinary(bytes, p, 1, TEXT_COMPACTION, sb); - } - else - { - //Mode latch performed by encodeBinary() - encodeBinary(bytes, - toBytes(msg.Substring(0, p), encoding).Length, - toBytes(msg.Substring(p, b), encoding).Length, - encodingMode, - sb); - encodingMode = BYTE_COMPACTION; - textSubMode = SUBMODE_ALPHA; //Reset after latch - } - p += b; - } - } - } - } - - return sb.ToString(); - } - - private static bool Contains(string[] stringArray, string lookFor) - { - var result = false; - lookFor = lookFor.ToUpper(); - for (var index = 0; index < stringArray.Length; index++) - { - if (stringArray[index] == lookFor) - { - result = true; - break; - } - } - - return result; - } - - private static byte[] toBytes(String msg, Encoding encoding) - { - // Defer instantiating default Charset until needed, since it may be for an unsupported - // encoding. - if (encoding == null) - { - try - { - encoding = Encoding.GetEncoding(DEFAULT_ENCODING_NAME); - } - catch (Exception ) - { - // continue - } - if (encoding == null) - { - // Fallbacks - try - { -#if WindowsCE - try - { - encoding = Encoding.GetEncoding(1252); - } - catch (PlatformNotSupportedException) - { - // WindowsCE doesn't support all encodings. But it is device depended. - // So we try here some different ones - encoding = Encoding.GetEncoding("CP437"); - } -#else - // Silverlight supports only UTF-8 and UTF-16 out-of-the-box - encoding = Encoding.GetEncoding("UTF-8"); -#endif - - } - catch (Exception uce) - { - throw new WriterException("No support for any encoding: " + DEFAULT_ENCODING_NAME, uce); - } - } - } - return encoding.GetBytes(msg); - } - - /// - /// Encode parts of the message using Text Compaction as described in ISO/IEC 15438:2001(E), - /// chapter 4.4.2. - /// - /// the message - /// the start position within the message - /// the number of characters to encode - /// receives the encoded codewords - /// should normally be SUBMODE_ALPHA - /// the text submode in which this method ends - /// - private static int encodeText(String msg, - int startpos, - int count, - StringBuilder sb, - int initialSubmode) - { - StringBuilder tmp = new StringBuilder(count); - int submode = initialSubmode; - int idx = 0; - while (true) - { - char ch = msg[startpos + idx]; - switch (submode) - { - case SUBMODE_ALPHA: - if (isAlphaUpper(ch)) - { - if (ch == ' ') - { - tmp.Append((char) 26); //space - } - else - { - tmp.Append((char) (ch - 65)); - } - } - else - { - if (isAlphaLower(ch)) - { - submode = SUBMODE_LOWER; - tmp.Append((char) 27); //ll - continue; - } - else if (isMixed(ch)) - { - submode = SUBMODE_MIXED; - tmp.Append((char) 28); //ml - continue; - } - else - { - tmp.Append((char) 29); //ps - tmp.Append((char) PUNCTUATION[ch]); - break; - } - } - break; - case SUBMODE_LOWER: - if (isAlphaLower(ch)) - { - if (ch == ' ') - { - tmp.Append((char) 26); //space - } - else - { - tmp.Append((char) (ch - 97)); - } - } - else - { - if (isAlphaUpper(ch)) - { - tmp.Append((char) 27); //as - tmp.Append((char) (ch - 65)); - //space cannot happen here, it is also in "Lower" - break; - } - else if (isMixed(ch)) - { - submode = SUBMODE_MIXED; - tmp.Append((char) 28); //ml - continue; - } - else - { - tmp.Append((char) 29); //ps - tmp.Append((char) PUNCTUATION[ch]); - break; - } - } - break; - case SUBMODE_MIXED: - if (isMixed(ch)) - { - tmp.Append((char) MIXED[ch]); - } - else - { - if (isAlphaUpper(ch)) - { - submode = SUBMODE_ALPHA; - tmp.Append((char) 28); //al - continue; - } - else if (isAlphaLower(ch)) - { - submode = SUBMODE_LOWER; - tmp.Append((char) 27); //ll - continue; - } - else - { - if (startpos + idx + 1 < count) - { - char next = msg[startpos + idx + 1]; - if (isPunctuation(next)) - { - submode = SUBMODE_PUNCTUATION; - tmp.Append((char) 25); //pl - continue; - } - } - tmp.Append((char) 29); //ps - tmp.Append((char) PUNCTUATION[ch]); - } - } - break; - default: //SUBMODE_PUNCTUATION - if (isPunctuation(ch)) - { - tmp.Append((char) PUNCTUATION[ch]); - } - else - { - submode = SUBMODE_ALPHA; - tmp.Append((char) 29); //al - continue; - } - break; - } - idx++; - if (idx >= count) - { - break; - } - } - char h = (char) 0; - int len = tmp.Length; - for (int i = 0; i < len; i++) - { - bool odd = (i%2) != 0; - if (odd) - { - h = (char) ((h*30) + tmp[i]); - sb.Append(h); - } - else - { - h = tmp[i]; - } - } - if ((len%2) != 0) - { - sb.Append((char) ((h*30) + 29)); //ps - } - return submode; - } - - /// - /// Encode parts of the message using Byte Compaction as described in ISO/IEC 15438:2001(E), - /// chapter 4.4.3. The Unicode characters will be converted to binary using the cp437 - /// codepage. - /// - /// the message converted to a byte array - /// the start position within the message - /// the number of bytes to encode - /// the mode from which this method starts - /// receives the encoded codewords - /// - private static void encodeBinary(byte[] bytes, - int startpos, - int count, - int startmode, - StringBuilder sb) - { - if (count == 1 && startmode == TEXT_COMPACTION) - { - sb.Append((char) SHIFT_TO_BYTE); - } - else - { - bool sixpack = ((count % 6) == 0); - if (sixpack) - { - sb.Append((char)LATCH_TO_BYTE); - } - else - { - sb.Append((char)LATCH_TO_BYTE_PADDED); - } - } - - int idx = startpos; - // Encode sixpacks - if (count >= 6) - { - char[] chars = new char[5]; - while ((startpos + count - idx) >= 6) - { - long t = 0; - for (int i = 0; i < 6; i++) - { - t <<= 8; - t += bytes[idx + i] & 0xff; - } - for (int i = 0; i < 5; i++) - { - chars[i] = (char) (t%900); - t /= 900; - } - for (int i = chars.Length - 1; i >= 0; i--) - { - sb.Append(chars[i]); - } - idx += 6; - } - } - //Encode rest (remaining n<5 bytes if any) - for (int i = idx; i < startpos + count; i++) - { - int ch = bytes[i] & 0xff; - sb.Append((char) ch); - } - } - - private static void encodeNumeric(String msg, int startpos, int count, StringBuilder sb) - { - int idx = 0; - StringBuilder tmp = new StringBuilder(count/3 + 1); - BigInteger num900 = new BigInteger(900); - BigInteger num0 = new BigInteger(0); - while (idx < count - 1) - { - tmp.Length = 0; - int len = Math.Min(44, count - idx); - String part = '1' + msg.Substring(startpos + idx, len); - BigInteger bigint = BigInteger.Parse(part); - do - { - BigInteger c = bigint%num900; - tmp.Append((char) c); - bigint = BigInteger.Divide(bigint, num900); - } while (!bigint.Equals(num0)); - - //Reverse temporary string - for (int i = tmp.Length - 1; i >= 0; i--) - { - sb.Append(tmp[i]); - } - idx += len; - } - } - - - private static bool isDigit(char ch) - { - return ch >= '0' && ch <= '9'; - } - - private static bool isAlphaUpper(char ch) - { - return ch == ' ' || (ch >= 'A' && ch <= 'Z'); - } - - private static bool isAlphaLower(char ch) - { - return ch == ' ' || (ch >= 'a' && ch <= 'z'); - } - - private static bool isMixed(char ch) - { - return MIXED[ch] != -1; - } - - private static bool isPunctuation(char ch) - { - return PUNCTUATION[ch] != -1; - } - - private static bool isText(char ch) - { - return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126); - } - - /// - /// Determines the number of consecutive characters that are encodable using numeric compaction. - /// - /// the message - /// the start position within the message - /// the requested character count - /// - private static int determineConsecutiveDigitCount(String msg, int startpos) - { - int count = 0; - int len = msg.Length; - int idx = startpos; - if (idx < len) - { - char ch = msg[idx]; - while (isDigit(ch) && idx < len) - { - count++; - idx++; - if (idx < len) - { - ch = msg[idx]; - } - } - } - return count; - } - - /// - /// Determines the number of consecutive characters that are encodable using text compaction. - /// - /// the message - /// the start position within the message - /// the requested character count - /// - private static int determineConsecutiveTextCount(String msg, int startpos) - { - int len = msg.Length; - int idx = startpos; - while (idx < len) - { - char ch = msg[idx]; - int numericCount = 0; - while (numericCount < 13 && isDigit(ch) && idx < len) - { - numericCount++; - idx++; - if (idx < len) - { - ch = msg[idx]; - } - } - if (numericCount >= 13) - { - return idx - startpos - numericCount; - } - if (numericCount > 0) - { - //Heuristic: All text-encodable chars or digits are binary encodable - continue; - } - ch = msg[idx]; - - //Check if character is encodable - if (!isText(ch)) - { - break; - } - idx++; - } - return idx - startpos; - } - - /// - /// Determines the number of consecutive characters that are encodable using binary compaction. - /// - /// the message - /// the message converted to a byte array - /// the start position within the message - /// the requested character count - /// - private static int determineConsecutiveBinaryCount(String msg, byte[] bytes, int startpos) - { - int len = msg.Length; - int idx = startpos; - int idxb = idx; // bytes index (may differ from idx for utf-8 and other unicode encodings) - while (idx < len) - { - char ch = msg[idx]; - int numericCount = 0; - - while (numericCount < 13 && isDigit(ch)) - { - numericCount++; - //textCount++; - int i = idx + numericCount; - if (i >= len) - { - break; - } - ch = msg[i]; - } - if (numericCount >= 13) - { - return idx - startpos; - } - ch = msg[idx]; - - //Check if character is encodable - //Sun returns a ASCII 63 (?) for a character that cannot be mapped. Let's hope all - //other VMs do the same - if (bytes[idxb] == 63 && ch != '?') - { - throw new WriterException("Non-encodable character detected: " + ch + " (Unicode: " + (int) ch + ')'); - } - idx++; - idxb++; - if (ch >= 256) // for non-ascii symbols - idxb++; - } - return idx - startpos; - } - - private static void encodingECI(int eci, StringBuilder sb) - { - if (eci >= 0 && eci < 900) - { - sb.Append((char) ECI_CHARSET); - sb.Append((char) eci); - } - else if (eci < 810900) - { - sb.Append((char) ECI_GENERAL_PURPOSE); - sb.Append((char) (eci/900 - 1)); - sb.Append((char) (eci%900)); - } - else if (eci < 811800) - { - sb.Append((char) ECI_USER_DEFINED); - sb.Append((char) (810900 - eci)); - } - else - { - throw new WriterException("ECI number not in valid range from 0..811799, but was " + eci); - } - } - } -} diff --git a/zxing.core/xx/presentation/BarcodeReader.Extensions.cs b/zxing.core/xx/presentation/BarcodeReader.Extensions.cs deleted file mode 100644 index 0194ed4..0000000 --- a/zxing.core/xx/presentation/BarcodeReader.Extensions.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 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 -{ - using System.Windows.Media.Imaging; - - /// - /// extensions methods which are working directly on any IBarcodeReaderGeneric implementation - /// - public static class BarcodeReaderExtensions - { - /// - /// uses the IBarcodeReaderGeneric implementation and the class for decoding - /// - /// - /// - /// - public static Result Decode(this IBarcodeReaderGeneric reader, BitmapSource image) - { - var luminanceSource = new BitmapSourceLuminanceSource(image); - return reader.Decode(luminanceSource); - } - - /// - /// uses the IBarcodeReaderGeneric implementation and the class for decoding - /// - /// - /// - /// - public static Result[] DecodeMultiple(this IBarcodeReaderGeneric reader, BitmapSource image) - { - var luminanceSource = new BitmapSourceLuminanceSource(image); - return reader.DecodeMultiple(luminanceSource); - } - } -} diff --git a/zxing.core/xx/presentation/BarcodeReader.cs b/zxing.core/xx/presentation/BarcodeReader.cs deleted file mode 100644 index 0b6806e..0000000 --- a/zxing.core/xx/presentation/BarcodeReader.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* -* 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.Windows.Media.Imaging; - -namespace ZXing.Presentation -{ - /// - /// A smart class to decode the barcode inside a bitmap object which is derived from BitmapSource - /// - public class BarcodeReader : BarcodeReader - { - private static readonly Func defaultCreateLuminanceSource = - bitmap => new BitmapSourceLuminanceSource(bitmap); - - /// - /// Initializes a new instance of the class. - /// - public BarcodeReader() - : this(null, defaultCreateLuminanceSource, null) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, default is used - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - public BarcodeReader(Reader reader, - Func createLuminanceSource, - Func createBinarizer - ) - : base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Sets the reader which should be used to find and decode the barcode. - /// If null then MultiFormatReader is used - /// Sets the function to create a luminance source object for a bitmap. - /// If null, default is used - /// Sets the function to create a binarizer object for a luminance source. - /// If null then HybridBinarizer is used - /// The create RGB luminance source. - public BarcodeReader(Reader reader, - Func createLuminanceSource, - Func createBinarizer, - Func createRGBLuminanceSource - ) - : base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer, createRGBLuminanceSource) - { - } - } -} diff --git a/zxing.core/xx/presentation/BarcodeWriter.Extensions.cs b/zxing.core/xx/presentation/BarcodeWriter.Extensions.cs deleted file mode 100644 index 3d4c77a..0000000 --- a/zxing.core/xx/presentation/BarcodeWriter.Extensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 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 -{ - using System.Windows.Media.Imaging; - - using Rendering; - - /// - /// extensions methods which are working directly on any BarcodeWriterGeneric implementation - /// - public static class BarcodeWriterExtensions - { - /// - /// uses the BarcodeWriterGeneric implementation and the class for decoding - /// - /// - /// - /// - public static WriteableBitmap WriteAsWriteableBitmap(this IBarcodeWriterGeneric writer, string content) - { - var bitmatrix = writer.Encode(content); - var renderer = new WriteableBitmapRenderer(); - return renderer.Render(bitmatrix, writer.Format, content, writer.Options); - } - } -} diff --git a/zxing.core/xx/presentation/BarcodeWriter.cs b/zxing.core/xx/presentation/BarcodeWriter.cs deleted file mode 100644 index dd88f32..0000000 --- a/zxing.core/xx/presentation/BarcodeWriter.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* -* Copyright 2014 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.Windows.Media.Imaging; - -using ZXing.Rendering; - -namespace ZXing.Presentation -{ - /// - /// A smart class to encode some content to a barcode image - /// - public class BarcodeWriter : BarcodeWriterGeneric - { - /// - /// Initializes a new instance of the class. - /// - public BarcodeWriter() - { - Renderer = new WriteableBitmapRenderer(); - } - } -} diff --git a/zxing.core/xx/presentation/BarcodeWriterGeometry.Extensions.cs b/zxing.core/xx/presentation/BarcodeWriterGeometry.Extensions.cs deleted file mode 100644 index 6d7b364..0000000 --- a/zxing.core/xx/presentation/BarcodeWriterGeometry.Extensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 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 -{ - using System.Windows.Media; - - using Rendering; - - /// - /// extensions methods which are working directly on any BarcodeWriterGeneric implementation - /// - public static class BarcodeWriterGeometryExtensions - { - /// - /// uses the BarcodeWriterGeneric implementation and the class for decoding - /// - /// - /// - /// - public static Geometry WriteAsGeometry(this IBarcodeWriterGeneric writer, string content) - { - var bitmatrix = writer.Encode(content); - var renderer = new GeometryRenderer(); - return renderer.Render(bitmatrix, writer.Format, content, writer.Options); - } - } -} diff --git a/zxing.core/xx/presentation/BarcodeWriterGeometry.cs b/zxing.core/xx/presentation/BarcodeWriterGeometry.cs deleted file mode 100644 index 559c267..0000000 --- a/zxing.core/xx/presentation/BarcodeWriterGeometry.cs +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2014 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.Windows.Media; - -using ZXing.Rendering; - -namespace ZXing.Presentation -{ - /// - /// A smart class to encode some content to a barcode image into a geometry - /// Autor: Rob Fonseca-Ensor - /// - public class BarcodeWriterGeometry : BarcodeWriter - { - /// - /// Initializes a new instance of the class. - /// - public BarcodeWriterGeometry() - { - Renderer = new GeometryRenderer(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/project.json b/zxing.core/xx/project.json deleted file mode 100644 index 3121628..0000000 --- a/zxing.core/xx/project.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "title": "ZXing for .NET Core", - "version": "0.14.0.2", - "projectUrl": "https://github.com/abrodersen/zxing-core", - "buildOptions": { - "compile": [ "**/*.cs" ], - "debugType": "portable" - }, - "packOptions": { - "owners": [ "ZXing.Net authors", "Aaron Brodersen" ], - "authors": [ "ZXing.Net authors", "Aaron Brodersen" ], - "summary": "zxing-core is a fork of ZXing.Net. It has been modified to be compatible with .NET Core.", - "licenseUrl": "https://raw.githubusercontent.com/abrodersen/zxing-core/master/LICENSE", - "iconUrl": "https://raw.githubusercontent.com/abrodersen/zxing-core/master/logo.jpg", - "repository": { - "type": "git", - "url": "git://github.com/abrodersen/zxing-core" - }, - "tags": [ - "ZXing", "barcode", "scanning", "1D", "2D", "UPC-A", "UPC-E", "EAN-8", "EAN-13", "QR", "ITF", "Codabar", "RSS-14", "Data", "Matrix", "PDF", "417", "PDF417", "Aztec" - ], - "releaseNotes": "update to netstandard1.3" - }, - "dependencies": { }, - "frameworks" : { - "netstandard1.3": { - "dependencies": { - "NETStandard.Library": "1.6.0" - } - } - } -} diff --git a/zxing.core/xx/qrcode/QRCodeReader.cs b/zxing.core/xx/qrcode/QRCodeReader.cs deleted file mode 100644 index 83c3fa8..0000000 --- a/zxing.core/xx/qrcode/QRCodeReader.cs +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.QrCode.Internal; - -namespace ZXing.QrCode -{ - /// - /// This implementation can detect and decode QR Codes in an image. - /// Sean Owen - /// - public class QRCodeReader : Reader - { - private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0]; - - private readonly Decoder decoder = new Decoder(); - - /// - /// Gets the decoder. - /// - /// - protected Decoder getDecoder() - { - return decoder; - } - - /// - /// Locates and decodes a QR code in an image. - /// - /// a String representing the content encoded by the QR code - /// - public Result decode(BinaryBitmap image) - { - return decode(image, null); - } - - /// - /// Locates and decodes a barcode in some format within an image. This method also accepts - /// hints, each possibly associated to some data, which may help the implementation decode. - /// - /// image of barcode to decode - /// passed as a from - /// to arbitrary data. The - /// meaning of the data depends upon the hint type. The implementation may or may not do - /// anything with these hints. - /// - /// String which the barcode encodes - /// - public Result decode(BinaryBitmap image, IDictionary hints) - { - DecoderResult decoderResult; - ResultPoint[] points; - if (image == null || image.BlackMatrix == null) - { - // something is wrong with the image - return null; - } - if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) - { - var bits = extractPureBits(image.BlackMatrix); - if (bits == null) - return null; - decoderResult = decoder.decode(bits, hints); - points = NO_POINTS; - } - else - { - var detectorResult = new Detector(image.BlackMatrix).detect(hints); - if (detectorResult == null) - return null; - decoderResult = decoder.decode(detectorResult.Bits, hints); - points = detectorResult.Points; - } - if (decoderResult == null) - return null; - - // If the code was mirrored: swap the bottom-left and the top-right points. - var data = decoderResult.Other as QRCodeDecoderMetaData; - if (data != null) - { - data.applyMirroredCorrection(points); - } - - var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE); - var byteSegments = decoderResult.ByteSegments; - if (byteSegments != null) - { - result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); - } - var ecLevel = decoderResult.ECLevel; - if (ecLevel != null) - { - result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); - } - if (decoderResult.StructuredAppend) - { - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, decoderResult.StructuredAppendSequenceNumber); - result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, decoderResult.StructuredAppendParity); - } - return result; - } - - /// - /// Resets any internal state the implementation has after a decode, to prepare it - /// for reuse. - /// - public void reset() - { - // do nothing - } - - /// - /// This method detects a code in a "pure" image -- that is, pure monochrome image - /// which contains only an unrotated, unskewed, image of a code, with some white border - /// around it. This is a specialized method that works exceptionally fast in this special - /// case. - /// - /// - /// - private static BitMatrix extractPureBits(BitMatrix image) - { - int[] leftTopBlack = image.getTopLeftOnBit(); - int[] rightBottomBlack = image.getBottomRightOnBit(); - if (leftTopBlack == null || rightBottomBlack == null) - { - return null; - } - - float moduleSize; - if (!QRCodeReader.moduleSize(leftTopBlack, image, out moduleSize)) - return null; - - int top = leftTopBlack[1]; - int bottom = rightBottomBlack[1]; - int left = leftTopBlack[0]; - int right = rightBottomBlack[0]; - - // Sanity check! - if (left >= right || top >= bottom) - { - return null; - } - - if (bottom - top != right - left) - { - // Special case, where bottom-right module wasn't black so we found something else in the last row - // Assume it's a square, so use height as the width - right = left + (bottom - top); - } - - int matrixWidth = (int)Math.Round((right - left + 1) / moduleSize); - int matrixHeight = (int)Math.Round((bottom - top + 1) / moduleSize); - if (matrixWidth <= 0 || matrixHeight <= 0) - { - return null; - } - if (matrixHeight != matrixWidth) - { - // Only possibly decode square regions - return null; - } - - // Push in the "border" by half the module width so that we start - // sampling in the middle of the module. Just in case the image is a - // little off, this will help recover. - int nudge = (int)(moduleSize / 2.0f); - top += nudge; - left += nudge; - - // But careful that this does not sample off the edge - // "right" is the farthest-right valid pixel location -- right+1 is not necessarily - // This is positive by how much the inner x loop below would be too large - int nudgedTooFarRight = left + (int)((matrixWidth - 1) * moduleSize) - right; - if (nudgedTooFarRight > 0) - { - if (nudgedTooFarRight > nudge) - { - // Neither way fits; abort - return null; - } - left -= nudgedTooFarRight; - } - // See logic above - int nudgedTooFarDown = top + (int)((matrixHeight - 1) * moduleSize) - bottom; - if (nudgedTooFarDown > 0) - { - if (nudgedTooFarDown > nudge) - { - // Neither way fits; abort - return null; - } - top -= nudgedTooFarDown; - } - - // Now just read off the bits - BitMatrix bits = new BitMatrix(matrixWidth, matrixHeight); - for (int y = 0; y < matrixHeight; y++) - { - int iOffset = top + (int)(y * moduleSize); - for (int x = 0; x < matrixWidth; x++) - { - if (image[left + (int)(x * moduleSize), iOffset]) - { - bits[x, y] = true; - } - } - } - return bits; - } - - private static bool moduleSize(int[] leftTopBlack, BitMatrix image, out float msize) - { - int height = image.Height; - int width = image.Width; - int x = leftTopBlack[0]; - int y = leftTopBlack[1]; - bool inBlack = true; - int transitions = 0; - while (x < width && y < height) - { - if (inBlack != image[x, y]) - { - if (++transitions == 5) - { - break; - } - inBlack = !inBlack; - } - x++; - y++; - } - if (x == width || y == height) - { - msize = 0.0f; - return false; - } - msize = (x - leftTopBlack[0]) / 7.0f; - return true; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/QRCodeWriter.cs b/zxing.core/xx/qrcode/QRCodeWriter.cs deleted file mode 100644 index 0bf1bdf..0000000 --- a/zxing.core/xx/qrcode/QRCodeWriter.cs +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.QrCode.Internal; - -namespace ZXing.QrCode -{ - /// - /// This object renders a QR Code as a BitMatrix 2D array of greyscale values. - /// - /// dswitkin@google.com (Daniel Switkin) - /// - public sealed class QRCodeWriter : Writer - { - private const int QUIET_ZONE_SIZE = 4; - - /// - /// Encode a barcode using the default settings. - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - /// - public BitMatrix encode(String contents, BarcodeFormat format, int width, int height) - { - return encode(contents, format, width, height, null); - } - - /// - /// - /// The contents to encode in the barcode - /// The barcode format to generate - /// The preferred width in pixels - /// The preferred height in pixels - /// Additional parameters to supply to the encoder - /// - /// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white) - /// - public BitMatrix encode(String contents, - BarcodeFormat format, - int width, - int height, - IDictionary hints) - { - if (String.IsNullOrEmpty(contents)) - { - throw new ArgumentException("Found empty contents"); - } - - if (format != BarcodeFormat.QR_CODE) - { - throw new ArgumentException("Can only encode QR_CODE, but got " + format); - } - - if (width < 0 || height < 0) - { - throw new ArgumentException("Requested dimensions are too small: " + width + 'x' + height); - } - - var errorCorrectionLevel = ErrorCorrectionLevel.L; - int quietZone = QUIET_ZONE_SIZE; - if (hints != null) - { - var requestedECLevel = hints.ContainsKey(EncodeHintType.ERROR_CORRECTION) ? (ErrorCorrectionLevel)hints[EncodeHintType.ERROR_CORRECTION] : null; - if (requestedECLevel != null) - { - errorCorrectionLevel = requestedECLevel; - } - var quietZoneInt = hints.ContainsKey(EncodeHintType.MARGIN) ? (int)hints[EncodeHintType.MARGIN] : (int?)null; - if (quietZoneInt != null) - { - quietZone = quietZoneInt.Value; - } - } - - var code = Encoder.encode(contents, errorCorrectionLevel, hints); - return renderResult(code, width, height, quietZone); - } - - // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses - // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap). - private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone) - { - var input = code.Matrix; - if (input == null) - { - throw new InvalidOperationException(); - } - int inputWidth = input.Width; - int inputHeight = input.Height; - int qrWidth = inputWidth + (quietZone << 1); - int qrHeight = inputHeight + (quietZone << 1); - int outputWidth = Math.Max(width, qrWidth); - int outputHeight = Math.Max(height, qrHeight); - - int multiple = Math.Min(outputWidth / qrWidth, outputHeight / qrHeight); - // Padding includes both the quiet zone and the extra white pixels to accommodate the requested - // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone. - // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will - // handle all the padding from 100x100 (the actual QR) up to 200x160. - int leftPadding = (outputWidth - (inputWidth * multiple)) / 2; - int topPadding = (outputHeight - (inputHeight * multiple)) / 2; - - var output = new BitMatrix(outputWidth, outputHeight); - - for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) - { - // Write the contents of this row of the barcode - for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) - { - if (input[inputX, inputY] == 1) - { - output.setRegion(outputX, outputY, multiple, multiple); - } - } - } - - return output; - } - } -} diff --git a/zxing.core/xx/qrcode/decoder/BitMatrixParser.cs b/zxing.core/xx/qrcode/decoder/BitMatrixParser.cs deleted file mode 100644 index 90d911f..0000000 --- a/zxing.core/xx/qrcode/decoder/BitMatrixParser.cs +++ /dev/null @@ -1,281 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using ZXing.Common; - -namespace ZXing.QrCode.Internal -{ - /// Sean Owen - sealed class BitMatrixParser - { - private readonly BitMatrix bitMatrix; - private Version parsedVersion; - private FormatInformation parsedFormatInfo; - private bool mirrored; - - /// {@link BitMatrix} to parse - /// ReaderException if dimension is not >= 21 and 1 mod 4 - internal static BitMatrixParser createBitMatrixParser(BitMatrix bitMatrix) - { - int dimension = bitMatrix.Height; - if (dimension < 21 || (dimension & 0x03) != 1) - { - return null; - } - return new BitMatrixParser(bitMatrix); - } - - private BitMatrixParser(BitMatrix bitMatrix) - { - // Should only be called from createBitMatrixParser with the important checks before - this.bitMatrix = bitMatrix; - } - - ///

Reads format information from one of its two locations within the QR Code.

- /// - ///
- /// {@link FormatInformation} encapsulating the QR Code's format info - /// - /// ReaderException if both format information locations cannot be parsed as - /// the valid encoding of format information - /// - internal FormatInformation readFormatInformation() - { - if (parsedFormatInfo != null) - { - return parsedFormatInfo; - } - - // Read top-left format info bits - int formatInfoBits1 = 0; - for (int i = 0; i < 6; i++) - { - formatInfoBits1 = copyBit(i, 8, formatInfoBits1); - } - // .. and skip a bit in the timing pattern ... - formatInfoBits1 = copyBit(7, 8, formatInfoBits1); - formatInfoBits1 = copyBit(8, 8, formatInfoBits1); - formatInfoBits1 = copyBit(8, 7, formatInfoBits1); - // .. and skip a bit in the timing pattern ... - for (int j = 5; j >= 0; j--) - { - formatInfoBits1 = copyBit(8, j, formatInfoBits1); - } - // Read the top-right/bottom-left pattern too - int dimension = bitMatrix.Height; - int formatInfoBits2 = 0; - int jMin = dimension - 7; - for (int j = dimension - 1; j >= jMin; j--) - { - formatInfoBits2 = copyBit(8, j, formatInfoBits2); - } - for (int i = dimension - 8; i < dimension; i++) - { - formatInfoBits2 = copyBit(i, 8, formatInfoBits2); - } - - parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2); - if (parsedFormatInfo != null) - { - return parsedFormatInfo; - } - return null; - } - - ///

Reads version information from one of its two locations within the QR Code.

- /// - ///
- /// {@link Version} encapsulating the QR Code's version - /// - /// ReaderException if both version information locations cannot be parsed as - /// the valid encoding of version information - /// - internal Version readVersion() - { - if (parsedVersion != null) - { - return parsedVersion; - } - - int dimension = bitMatrix.Height; - - int provisionalVersion = (dimension - 17) >> 2; - if (provisionalVersion <= 6) - { - return Version.getVersionForNumber(provisionalVersion); - } - - // Read top-right version info: 3 wide by 6 tall - int versionBits = 0; - int ijMin = dimension - 11; - for (int j = 5; j >= 0; j--) - { - for (int i = dimension - 9; i >= ijMin; i--) - { - versionBits = copyBit(i, j, versionBits); - } - } - - parsedVersion = Version.decodeVersionInformation(versionBits); - if (parsedVersion != null && parsedVersion.DimensionForVersion == dimension) - { - return parsedVersion; - } - - // Hmm, failed. Try bottom left: 6 wide by 3 tall - versionBits = 0; - for (int i = 5; i >= 0; i--) - { - for (int j = dimension - 9; j >= ijMin; j--) - { - versionBits = copyBit(i, j, versionBits); - } - } - - parsedVersion = Version.decodeVersionInformation(versionBits); - if (parsedVersion != null && parsedVersion.DimensionForVersion == dimension) - { - return parsedVersion; - } - return null; - } - - private int copyBit(int i, int j, int versionBits) - { - bool bit = mirrored ? bitMatrix[j, i] : bitMatrix[i, j]; - return bit ? (versionBits << 1) | 0x1 : versionBits << 1; - } - - ///

Reads the bits in the {@link BitMatrix} representing the finder pattern in the - /// correct order in order to reconstruct the codewords bytes contained within the - /// QR Code.

- /// - ///
- /// bytes encoded within the QR Code - /// - /// ReaderException if the exact number of bytes expected is not read - internal byte[] readCodewords() - { - FormatInformation formatInfo = readFormatInformation(); - if (formatInfo == null) - return null; - Version version = readVersion(); - if (version == null) - return null; - - // Get the data mask for the format used in this QR Code. This will exclude - // some bits from reading as we wind through the bit matrix. - DataMask dataMask = DataMask.forReference(formatInfo.DataMask); - int dimension = bitMatrix.Height; - dataMask.unmaskBitMatrix(bitMatrix, dimension); - - BitMatrix functionPattern = version.buildFunctionPattern(); - - bool readingUp = true; - byte[] result = new byte[version.TotalCodewords]; - int resultOffset = 0; - int currentByte = 0; - int bitsRead = 0; - // Read columns in pairs, from right to left - for (int j = dimension - 1; j > 0; j -= 2) - { - if (j == 6) - { - // Skip whole column with vertical alignment pattern; - // saves time and makes the other code proceed more cleanly - j--; - } - // Read alternatingly from bottom to top then top to bottom - for (int count = 0; count < dimension; count++) - { - int i = readingUp ? dimension - 1 - count : count; - for (int col = 0; col < 2; col++) - { - // Ignore bits covered by the function pattern - if (!functionPattern[j - col, i]) - { - // Read a bit - bitsRead++; - currentByte <<= 1; - if (bitMatrix[j - col, i]) - { - currentByte |= 1; - } - // If we've made a whole byte, save it off - if (bitsRead == 8) - { - result[resultOffset++] = (byte)currentByte; - bitsRead = 0; - currentByte = 0; - } - } - } - } - readingUp ^= true; // readingUp = !readingUp; // switch directions - } - if (resultOffset != version.TotalCodewords) - { - return null; - } - return result; - } - - /** - * Revert the mask removal done while reading the code words. The bit matrix should revert to its original state. - */ - internal void remask() - { - if (parsedFormatInfo == null) - { - return; // We have no format information, and have no data mask - } - DataMask dataMask = DataMask.forReference(parsedFormatInfo.DataMask); - int dimension = bitMatrix.Height; - dataMask.unmaskBitMatrix(bitMatrix, dimension); - } - - /** - * Prepare the parser for a mirrored operation. - * This flag has effect only on the {@link #readFormatInformation()} and the - * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the - * {@link #mirror()} method should be called. - * - * @param mirror Whether to read version and format information mirrored. - */ - internal void setMirror(bool mirror) - { - parsedVersion = null; - parsedFormatInfo = null; - mirrored = mirror; - } - - /** Mirror the bit matrix in order to attempt a second reading. */ - internal void mirror() - { - for (int x = 0; x < bitMatrix.Width; x++) - { - for (int y = x + 1; y < bitMatrix.Height; y++) - { - if (bitMatrix[x, y] != bitMatrix[y, x]) - { - bitMatrix.flip(y, x); - bitMatrix.flip(x, y); - } - } - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/DataBlock.cs b/zxing.core/xx/qrcode/decoder/DataBlock.cs deleted file mode 100644 index 97cabf6..0000000 --- a/zxing.core/xx/qrcode/decoder/DataBlock.cs +++ /dev/null @@ -1,146 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.QrCode.Internal -{ - ///

Encapsulates a block of data within a QR Code. QR Codes may split their data into - /// multiple blocks, each of which is a unit of data and error-correction codewords. Each - /// is represented by an instance of this class.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - internal sealed class DataBlock - { - private readonly int numDataCodewords; - private readonly byte[] codewords; - - private DataBlock(int numDataCodewords, byte[] codewords) - { - this.numDataCodewords = numDataCodewords; - this.codewords = codewords; - } - - ///

When QR Codes use multiple data blocks, they are actually interleaved. - /// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This - /// method will separate the data into original blocks.

- /// - ///
- /// bytes as read directly from the QR Code - /// - /// version of the QR Code - /// - /// error-correction level of the QR Code - /// - /// {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the - /// QR Code - /// - internal static DataBlock[] getDataBlocks(byte[] rawCodewords, Version version, ErrorCorrectionLevel ecLevel) - { - - if (rawCodewords.Length != version.TotalCodewords) - { - throw new System.ArgumentException(); - } - - // Figure out the number and size of data blocks used by this version and - // error correction level - Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); - - // First count the total number of data blocks - int totalBlocks = 0; - Version.ECB[] ecBlockArray = ecBlocks.getECBlocks(); - foreach (var ecBlock in ecBlockArray) - { - totalBlocks += ecBlock.Count; - } - - // Now establish DataBlocks of the appropriate size and number of data codewords - DataBlock[] result = new DataBlock[totalBlocks]; - int numResultBlocks = 0; - foreach (var ecBlock in ecBlockArray) - { - for (int i = 0; i < ecBlock.Count; i++) - { - int numDataCodewords = ecBlock.DataCodewords; - int numBlockCodewords = ecBlocks.ECCodewordsPerBlock + numDataCodewords; - result[numResultBlocks++] = new DataBlock(numDataCodewords, new byte[numBlockCodewords]); - } - } - - // All blocks have the same amount of data, except that the last n - // (where n may be 0) have 1 more byte. Figure out where these start. - int shorterBlocksTotalCodewords = result[0].codewords.Length; - int longerBlocksStartAt = result.Length - 1; - while (longerBlocksStartAt >= 0) - { - int numCodewords = result[longerBlocksStartAt].codewords.Length; - if (numCodewords == shorterBlocksTotalCodewords) - { - break; - } - longerBlocksStartAt--; - } - longerBlocksStartAt++; - - int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.ECCodewordsPerBlock; - // The last elements of result may be 1 element longer; - // first fill out as many elements as all of them have - int rawCodewordsOffset = 0; - for (int i = 0; i < shorterBlocksNumDataCodewords; i++) - { - for (int j = 0; j < numResultBlocks; j++) - { - result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; - } - } - // Fill out the last data block in the longer ones - for (int j = longerBlocksStartAt; j < numResultBlocks; j++) - { - result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; - } - // Now add in error correction blocks - int max = result[0].codewords.Length; - for (int i = shorterBlocksNumDataCodewords; i < max; i++) - { - for (int j = 0; j < numResultBlocks; j++) - { - int iOffset = j < longerBlocksStartAt ? i : i + 1; - result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; - } - } - return result; - } - - internal int NumDataCodewords - { - get - { - return numDataCodewords; - } - } - - internal byte[] Codewords - { - get - { - return codewords; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/DataMask.cs b/zxing.core/xx/qrcode/decoder/DataMask.cs deleted file mode 100644 index 2b4f2dd..0000000 --- a/zxing.core/xx/qrcode/decoder/DataMask.cs +++ /dev/null @@ -1,165 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using ZXing.Common; - -namespace ZXing.QrCode.Internal -{ - ///

Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations - /// of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix, - /// including areas used for finder patterns, timing patterns, etc. These areas should be unused - /// after the point they are unmasked anyway.

- /// - ///

Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position - /// and j is row position. In fact, as the text says, i is row position and j is column position.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - abstract class DataMask - { - /// See ISO 18004:2006 6.8.1 - private static readonly DataMask[] DATA_MASKS = new DataMask[] - { - new DataMask000(), - new DataMask001(), - new DataMask010(), - new DataMask011(), - new DataMask100(), - new DataMask101(), - new DataMask110(), - new DataMask111() - }; - - private DataMask() - { - } - - ///

Implementations of this method reverse the data masking process applied to a QR Code and - /// make its bits ready to read.

- /// - ///
- /// representation of QR Code bits - /// - /// dimension of QR Code, represented by bits, being unmasked - /// - internal void unmaskBitMatrix(BitMatrix bits, int dimension) - { - for (int i = 0; i < dimension; i++) - { - for (int j = 0; j < dimension; j++) - { - if (isMasked(i, j)) - { - bits.flip(j, i); - } - } - } - } - - internal abstract bool isMasked(int i, int j); - - /// a value between 0 and 7 indicating one of the eight possible - /// data mask patterns a QR Code may use - /// - /// {@link DataMask} encapsulating the data mask pattern - /// - internal static DataMask forReference(int reference) - { - if (reference < 0 || reference > 7) - { - throw new System.ArgumentException(); - } - return DATA_MASKS[reference]; - } - - /// 000: mask bits for which (x + y) mod 2 == 0 - private sealed class DataMask000 : DataMask - { - internal override bool isMasked(int i, int j) - { - return ((i + j) & 0x01) == 0; - } - } - - /// 001: mask bits for which x mod 2 == 0 - private sealed class DataMask001 : DataMask - { - internal override bool isMasked(int i, int j) - { - return (i & 0x01) == 0; - } - } - - /// 010: mask bits for which y mod 3 == 0 - private sealed class DataMask010 : DataMask - { - internal override bool isMasked(int i, int j) - { - return j % 3 == 0; - } - } - - /// 011: mask bits for which (x + y) mod 3 == 0 - private sealed class DataMask011 : DataMask - { - internal override bool isMasked(int i, int j) - { - return (i + j) % 3 == 0; - } - } - - /// 100: mask bits for which (x/2 + y/3) mod 2 == 0 - private sealed class DataMask100 : DataMask - { - internal override bool isMasked(int i, int j) - { - return ((((int)((uint)i >> 1)) + (j / 3)) & 0x01) == 0; - } - } - - /// 101: mask bits for which xy mod 2 + xy mod 3 == 0 - private sealed class DataMask101 : DataMask - { - internal override bool isMasked(int i, int j) - { - int temp = i * j; - return (temp & 0x01) + (temp % 3) == 0; - } - } - - /// 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0 - private sealed class DataMask110 : DataMask - { - internal override bool isMasked(int i, int j) - { - int temp = i * j; - return (((temp & 0x01) + (temp % 3)) & 0x01) == 0; - } - } - - /// 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0 - private sealed class DataMask111 : DataMask - { - internal override bool isMasked(int i, int j) - { - return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/DecodedBitStreamParser.cs b/zxing.core/xx/qrcode/decoder/DecodedBitStreamParser.cs deleted file mode 100644 index 4af430c..0000000 --- a/zxing.core/xx/qrcode/decoder/DecodedBitStreamParser.cs +++ /dev/null @@ -1,524 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -using ZXing.Common; - -namespace ZXing.QrCode.Internal -{ - ///

QR Codes can encode text as bits in one of several modes, and can use multiple modes - /// in one QR Code. This class decodes the bits back into text.

- /// - ///

See ISO 18004:2006, 6.4.3 - 6.4.7

- /// Sean Owen - ///
- internal static class DecodedBitStreamParser - { - /// - /// See ISO 18004:2006, 6.4.4 Table 5 - /// - private static readonly char[] ALPHANUMERIC_CHARS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', - 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - ' ', '$', '%', '*', '+', '-', '.', '/', ':' - }; - private const int GB2312_SUBSET = 1; - - internal static DecoderResult decode(byte[] bytes, - Version version, - ErrorCorrectionLevel ecLevel, - IDictionary hints) - { - var bits = new BitSource(bytes); - var result = new StringBuilder(50); - var byteSegments = new List(1); - var symbolSequence = -1; - var parityData = -1; - - try - { - CharacterSetECI currentCharacterSetECI = null; - bool fc1InEffect = false; - Mode mode; - do - { - // While still another segment to read... - if (bits.available() < 4) - { - // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here - mode = Mode.TERMINATOR; - } - else - { - try - { - mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits - } - catch (ArgumentException) - { - return null; - } - } - if (mode != Mode.TERMINATOR) - { - if (mode == Mode.FNC1_FIRST_POSITION || mode == Mode.FNC1_SECOND_POSITION) - { - // We do little with FNC1 except alter the parsed result a bit according to the spec - fc1InEffect = true; - } - else if (mode == Mode.STRUCTURED_APPEND) - { - if (bits.available() < 16) - { - return null; - } - // not really supported; but sequence number and parity is added later to the result metadata - // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue - 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)); - if (subset == GB2312_SUBSET) - { - if (!decodeHanziSegment(bits, result, countHanzi)) - return null; - } - } - else - { - // "Normal" QR code modes: - // How many characters will follow, encoded in this mode? - int count = bits.readBits(mode.getCharacterCountBits(version)); - if (mode == Mode.NUMERIC) - { - if (!decodeNumericSegment(bits, result, count)) - return null; - } - else if (mode == Mode.ALPHANUMERIC) - { - 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; - } - } - } - } - } while (mode != Mode.TERMINATOR); - } - catch (ArgumentException) - { - // from readBits() calls - return null; - } - -#if WindowsCE - var resultString = result.ToString().Replace("\n", "\r\n"); -#else - var resultString = result.ToString().Replace("\r\n", "\n").Replace("\n", Environment.NewLine); -#endif - return new DecoderResult(bytes, - resultString, - byteSegments.Count == 0 ? null : byteSegments, - ecLevel == null ? null : ecLevel.ToString(), - symbolSequence, parityData); - } - - /// - /// See specification GBT 18284-2000 - /// - /// The bits. - /// The result. - /// The count. - /// - 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 byteSegments, - IDictionary 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) - { - if (value >= ALPHANUMERIC_CHARS.Length) - { - throw FormatException.Instance; - } - return ALPHANUMERIC_CHARS[value]; - } - - private static bool decodeAlphanumericSegment(BitSource bits, - StringBuilder result, - int count, - bool fc1InEffect) - { - // Read two characters at a time - int start = result.Length; - while (count > 1) - { - if (bits.available() < 11) - { - return false; - } - int nextTwoCharsBits = bits.readBits(11); - result.Append(toAlphaNumericChar(nextTwoCharsBits / 45)); - result.Append(toAlphaNumericChar(nextTwoCharsBits % 45)); - count -= 2; - } - if (count == 1) - { - // special case: one character left - if (bits.available() < 6) - { - return false; - } - result.Append(toAlphaNumericChar(bits.readBits(6))); - } - - // See section 6.4.8.1, 6.4.8.2 - if (fc1InEffect) - { - // We need to massage the result a bit if in an FNC1 mode: - for (int i = start; i < result.Length; i++) - { - if (result[i] == '%') - { - if (i < result.Length - 1 && result[i + 1] == '%') - { - // %% is rendered as % - result.Remove(i + 1, 1); - } - else - { - // In alpha mode, % should be converted to FNC1 separator 0x1D - result.Remove(i, 1); - result.Insert(i, new[] { (char)0x1D }); - } - } - } - } - - return true; - } - - private static bool decodeNumericSegment(BitSource bits, - StringBuilder result, - int count) - { - // Read three digits at a time - while (count >= 3) - { - // Each 10 bits encodes three digits - if (bits.available() < 10) - { - return false; - } - int threeDigitsBits = bits.readBits(10); - if (threeDigitsBits >= 1000) - { - return false; - } - result.Append(toAlphaNumericChar(threeDigitsBits / 100)); - result.Append(toAlphaNumericChar((threeDigitsBits / 10) % 10)); - result.Append(toAlphaNumericChar(threeDigitsBits % 10)); - - count -= 3; - } - if (count == 2) - { - // Two digits left over to read, encoded in 7 bits - if (bits.available() < 7) - { - return false; - } - int twoDigitsBits = bits.readBits(7); - if (twoDigitsBits >= 100) - { - return false; - } - result.Append(toAlphaNumericChar(twoDigitsBits / 10)); - result.Append(toAlphaNumericChar(twoDigitsBits % 10)); - } - else if (count == 1) - { - // One digit left over to read - if (bits.available() < 4) - { - return false; - } - int digitBits = bits.readBits(4); - if (digitBits >= 10) - { - return false; - } - result.Append(toAlphaNumericChar(digitBits)); - } - - return true; - } - - private static int parseECIValue(BitSource bits) - { - int firstByte = bits.readBits(8); - if ((firstByte & 0x80) == 0) - { - // just one byte - return firstByte & 0x7F; - } - if ((firstByte & 0xC0) == 0x80) - { - // two bytes - int secondByte = bits.readBits(8); - return ((firstByte & 0x3F) << 8) | secondByte; - } - if ((firstByte & 0xE0) == 0xC0) - { - // three bytes - int secondThirdBytes = bits.readBits(16); - return ((firstByte & 0x1F) << 16) | secondThirdBytes; - } - throw new ArgumentException("Bad ECI bits starting with byte " + firstByte); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/Decoder.cs b/zxing.core/xx/qrcode/decoder/Decoder.cs deleted file mode 100644 index 9fefda7..0000000 --- a/zxing.core/xx/qrcode/decoder/Decoder.cs +++ /dev/null @@ -1,195 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Common.ReedSolomon; - -namespace ZXing.QrCode.Internal -{ - /// - ///

The main class which implements QR Code decoding -- as opposed to locating and extracting - /// the QR Code from an image.

- ///
- /// - /// Sean Owen - /// - public sealed class Decoder - { - private readonly ReedSolomonDecoder rsDecoder; - - /// - /// Initializes a new instance of the class. - /// - public Decoder() - { - rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256); - } - - /// - ///

Convenience method that can decode a QR Code represented as a 2D array of booleans. - /// "true" is taken to mean a black module.

- ///
- /// booleans representing white/black QR Code modules - /// decoding hints that should be used to influence decoding - /// - /// text and bytes encoded within the QR Code - /// - public DecoderResult decode(bool[][] image, IDictionary hints) - { - var dimension = image.Length; - var bits = new BitMatrix(dimension); - for (int i = 0; i < dimension; i++) - { - for (int j = 0; j < dimension; j++) - { - bits[j, i] = image[i][j]; - } - } - return decode(bits, hints); - } - - /// - ///

Decodes a QR Code represented as a {@link BitMatrix}. A 1 or "true" is taken to mean a black module.

- ///
- /// booleans representing white/black QR Code modules - /// decoding hints that should be used to influence decoding - /// - /// text and bytes encoded within the QR Code - /// - public DecoderResult decode(BitMatrix bits, IDictionary hints) - { - // Construct a parser and read version, error-correction level - var parser = BitMatrixParser.createBitMatrixParser(bits); - if (parser == null) - return null; - - var result = decode(parser, hints); - if (result == null) - { - // Revert the bit matrix - parser.remask(); - - // Will be attempting a mirrored reading of the version and format info. - parser.setMirror(true); - - // Preemptively read the version. - var version = parser.readVersion(); - if (version == null) - return null; - - // Preemptively read the format information. - var formatinfo = parser.readFormatInformation(); - if (formatinfo == null) - return null; - - /* - * Since we're here, this means we have successfully detected some kind - * of version and format information when mirrored. This is a good sign, - * that the QR code may be mirrored, and we should try once more with a - * mirrored content. - */ - // Prepare for a mirrored reading. - parser.mirror(); - - result = decode(parser, hints); - - if (result != null) - { - // Success! Notify the caller that the code was mirrored. - result.Other = new QRCodeDecoderMetaData(true); - } - } - - return result; - } - - private DecoderResult decode(BitMatrixParser parser, IDictionary hints) - { - Version version = parser.readVersion(); - if (version == null) - return null; - var formatinfo = parser.readFormatInformation(); - if (formatinfo == null) - return null; - ErrorCorrectionLevel ecLevel = formatinfo.ErrorCorrectionLevel; - - // Read codewords - byte[] codewords = parser.readCodewords(); - if (codewords == null) - return null; - // Separate into data blocks - DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version, ecLevel); - - // Count total number of data bytes - int totalBytes = 0; - foreach (var dataBlock in dataBlocks) - { - totalBytes += dataBlock.NumDataCodewords; - } - byte[] resultBytes = new byte[totalBytes]; - int resultOffset = 0; - - // Error-correct and copy data blocks together into a stream of bytes - foreach (var dataBlock in dataBlocks) - { - byte[] codewordBytes = dataBlock.Codewords; - int numDataCodewords = dataBlock.NumDataCodewords; - if (!correctErrors(codewordBytes, numDataCodewords)) - return null; - for (int i = 0; i < numDataCodewords; i++) - { - resultBytes[resultOffset++] = codewordBytes[i]; - } - } - - // Decode the contents of that stream of bytes - return DecodedBitStreamParser.decode(resultBytes, version, ecLevel, hints); - } - - /// - ///

Given data and error-correction codewords received, possibly corrupted by errors, attempts to - /// correct the errors in-place using Reed-Solomon error correction.

- ///
- /// data and error correction codewords - /// number of codewords that are data bytes - /// - private bool correctErrors(byte[] codewordBytes, int numDataCodewords) - { - int numCodewords = codewordBytes.Length; - // First read into an array of ints - int[] codewordsInts = new int[numCodewords]; - for (int i = 0; i < numCodewords; i++) - { - codewordsInts[i] = codewordBytes[i] & 0xFF; - } - int numECCodewords = codewordBytes.Length - numDataCodewords; - - if (!rsDecoder.decode(codewordsInts, numECCodewords)) - return false; - - // Copy back into array of bytes -- only need to worry about the bytes that were data - // We don't care about errors in the error-correction codewords - for (int i = 0; i < numDataCodewords; i++) - { - codewordBytes[i] = (byte)codewordsInts[i]; - } - - return true; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/ErrorCorrectionLevel.cs b/zxing.core/xx/qrcode/decoder/ErrorCorrectionLevel.cs deleted file mode 100644 index c87112f..0000000 --- a/zxing.core/xx/qrcode/decoder/ErrorCorrectionLevel.cs +++ /dev/null @@ -1,109 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.QrCode.Internal -{ - /// - ///

See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels - /// defined by the QR code standard.

- ///
- /// Sean Owen - public sealed class ErrorCorrectionLevel - { - /// L = ~7% correction - public static readonly ErrorCorrectionLevel L = new ErrorCorrectionLevel(0, 0x01, "L"); - /// M = ~15% correction - public static readonly ErrorCorrectionLevel M = new ErrorCorrectionLevel(1, 0x00, "M"); - /// Q = ~25% correction - public static readonly ErrorCorrectionLevel Q = new ErrorCorrectionLevel(2, 0x03, "Q"); - /// H = ~30% correction - public static readonly ErrorCorrectionLevel H = new ErrorCorrectionLevel(3, 0x02, "H"); - - private static readonly ErrorCorrectionLevel[] FOR_BITS = new [] { M, L, H, Q }; - - private readonly int bits; - - private ErrorCorrectionLevel(int ordinal, int bits, String name) - { - this.ordinal_Renamed_Field = ordinal; - this.bits = bits; - this.name = name; - } - - /// - /// Gets the bits. - /// - public int Bits - { - get - { - return bits; - } - } - - /// - /// Gets the name. - /// - public String Name - { - get - { - return name; - } - } - - private readonly int ordinal_Renamed_Field; - private readonly String name; - - /// - /// Ordinals this instance. - /// - /// - public int ordinal() - { - return ordinal_Renamed_Field; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - return name; - } - - /// - /// Fors the bits. - /// - /// int containing the two bits encoding a QR Code's error correction level - /// - /// representing the encoded error correction level - /// - public static ErrorCorrectionLevel forBits(int bits) - { - if (bits < 0 || bits >= FOR_BITS.Length) - { - throw new ArgumentException(); - } - return FOR_BITS[bits]; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/FormatInformation.cs b/zxing.core/xx/qrcode/decoder/FormatInformation.cs deleted file mode 100644 index 77691f0..0000000 --- a/zxing.core/xx/qrcode/decoder/FormatInformation.cs +++ /dev/null @@ -1,197 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.QrCode.Internal -{ - - ///

Encapsulates a QR Code's format information, including the data mask used and - /// error correction level.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - /// - /// - /// - /// - sealed class FormatInformation - { - private const int FORMAT_INFO_MASK_QR = 0x5412; - - /// See ISO 18004:2006, Annex C, Table C.1 - private static readonly int[][] FORMAT_INFO_DECODE_LOOKUP = new int[][] - { - new [] { 0x5412, 0x00 }, - new [] { 0x5125, 0x01 }, - new [] { 0x5E7C, 0x02 }, - new [] { 0x5B4B, 0x03 }, - new [] { 0x45F9, 0x04 }, - new [] { 0x40CE, 0x05 }, - new [] { 0x4F97, 0x06 }, - new [] { 0x4AA0, 0x07 }, - new [] { 0x77C4, 0x08 }, - new [] { 0x72F3, 0x09 }, - new [] { 0x7DAA, 0x0A }, - new [] { 0x789D, 0x0B }, - new [] { 0x662F, 0x0C }, - new [] { 0x6318, 0x0D }, - new [] { 0x6C41, 0x0E }, - new [] { 0x6976, 0x0F }, - new [] { 0x1689, 0x10 }, - new [] { 0x13BE, 0x11 }, - new [] { 0x1CE7, 0x12 }, - new [] { 0x19D0, 0x13 }, - new [] { 0x0762, 0x14 }, - new [] { 0x0255, 0x15 }, - new [] { 0x0D0C, 0x16 }, - new [] { 0x083B, 0x17 }, - new [] { 0x355F, 0x18 }, - new [] { 0x3068, 0x19 }, - new [] { 0x3F31, 0x1A }, - new [] { 0x3A06, 0x1B }, - new [] { 0x24B4, 0x1C }, - new [] { 0x2183, 0x1D }, - new [] { 0x2EDA, 0x1E }, - new [] { 0x2BED, 0x1F } - }; - - /// Offset i holds the number of 1 bits in the binary representation of i - private static readonly int[] BITS_SET_IN_HALF_BYTE = new [] - { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; - - private readonly ErrorCorrectionLevel errorCorrectionLevel; - private readonly byte dataMask; - - private FormatInformation(int formatInfo) - { - // Bits 3,4 - errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03); - // Bottom 3 bits - dataMask = (byte)(formatInfo & 0x07); - } - - internal static int numBitsDiffering(int a, int b) - { - a ^= b; // a now has a 1 bit exactly where its bit differs with b's - // Count bits set quickly with a series of lookups: - return BITS_SET_IN_HALF_BYTE[a & 0x0F] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 4)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 8)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 12)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 16)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 20)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 24)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 28)) & 0x0F)]; - } - - /// - /// Decodes the format information. - /// - /// format info indicator, with mask still applied - /// The masked format info2. - /// - /// information about the format it specifies, or null - /// if doesn't seem to match any known pattern - /// - internal static FormatInformation decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) - { - FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2); - if (formatInfo != null) - { - return formatInfo; - } - // Should return null, but, some QR codes apparently - // do not mask this info. Try again by actually masking the pattern - // first - return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR, - maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR); - } - - private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) - { - // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing - int bestDifference = Int32.MaxValue; - int bestFormatInfo = 0; - foreach (var decodeInfo in FORMAT_INFO_DECODE_LOOKUP) - { - int targetInfo = decodeInfo[0]; - if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) - { - // Found an exact match - return new FormatInformation(decodeInfo[1]); - } - int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo); - if (bitsDifference < bestDifference) - { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - if (maskedFormatInfo1 != maskedFormatInfo2) - { - // also try the other option - bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo); - if (bitsDifference < bestDifference) - { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - } - } - // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits - // differing means we found a match - if (bestDifference <= 3) - { - return new FormatInformation(bestFormatInfo); - } - return null; - } - - internal ErrorCorrectionLevel ErrorCorrectionLevel - { - get - { - return errorCorrectionLevel; - } - } - - internal byte DataMask - { - get - { - return dataMask; - } - } - - public override int GetHashCode() - { - return (errorCorrectionLevel.ordinal() << 3) | dataMask; - } - - public override bool Equals(Object o) - { - if (!(o is FormatInformation)) - { - return false; - } - var other = (FormatInformation)o; - return errorCorrectionLevel == other.errorCorrectionLevel && dataMask == other.dataMask; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/Mode.cs b/zxing.core/xx/qrcode/decoder/Mode.cs deleted file mode 100644 index 5beff18..0000000 --- a/zxing.core/xx/qrcode/decoder/Mode.cs +++ /dev/null @@ -1,179 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.QrCode.Internal -{ - /// - ///

See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which - /// data can be encoded to bits in the QR code standard.

- ///
- /// Sean Owen - public sealed class Mode - { - /// - /// Gets the name. - /// - public String Name - { - get - { - return name; - } - } - - // No, we can't use an enum here. J2ME doesn't support it. - - /// - /// - /// - public static readonly Mode TERMINATOR = new Mode(new int[] { 0, 0, 0 }, 0x00, "TERMINATOR"); // Not really a mode... - /// - /// - /// - public static readonly Mode NUMERIC = new Mode(new int[] { 10, 12, 14 }, 0x01, "NUMERIC"); - /// - /// - /// - public static readonly Mode ALPHANUMERIC = new Mode(new int[] { 9, 11, 13 }, 0x02, "ALPHANUMERIC"); - /// - /// - /// - public static readonly Mode STRUCTURED_APPEND = new Mode(new int[] { 0, 0, 0 }, 0x03, "STRUCTURED_APPEND"); // Not supported - /// - /// - /// - public static readonly Mode BYTE = new Mode(new int[] { 8, 16, 16 }, 0x04, "BYTE"); - /// - /// - /// - public static readonly Mode ECI = new Mode(null, 0x07, "ECI"); // character counts don't apply - /// - /// - /// - public static readonly Mode KANJI = new Mode(new int[] { 8, 10, 12 }, 0x08, "KANJI"); - /// - /// - /// - public static readonly Mode FNC1_FIRST_POSITION = new Mode(null, 0x05, "FNC1_FIRST_POSITION"); - /// - /// - /// - public static readonly Mode FNC1_SECOND_POSITION = new Mode(null, 0x09, "FNC1_SECOND_POSITION"); - /// See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. - public static readonly Mode HANZI = new Mode(new int[] { 8, 10, 12 }, 0x0D, "HANZI"); - - private readonly int[] characterCountBitsForVersions; - private readonly int bits; - private readonly String name; - - private Mode(int[] characterCountBitsForVersions, int bits, System.String name) - { - this.characterCountBitsForVersions = characterCountBitsForVersions; - this.bits = bits; - this.name = name; - } - - /// - /// Fors the bits. - /// - /// four bits encoding a QR Code data mode - /// - /// encoded by these bits - /// - /// if bits do not correspond to a known mode - public static Mode forBits(int bits) - { - switch (bits) - { - case 0x0: - return TERMINATOR; - case 0x1: - return NUMERIC; - case 0x2: - return ALPHANUMERIC; - case 0x3: - return STRUCTURED_APPEND; - case 0x4: - return BYTE; - case 0x5: - return FNC1_FIRST_POSITION; - case 0x7: - return ECI; - case 0x8: - return KANJI; - case 0x9: - return FNC1_SECOND_POSITION; - case 0xD: - // 0xD is defined in GBT 18284-2000, may not be supported in foreign country - return HANZI; - default: - throw new ArgumentException(); - } - } - - /// version in question - /// - /// number of bits used, in this QR Code symbol {@link Version}, to encode the - /// count of characters that will follow encoded in this {@link Mode} - /// - public int getCharacterCountBits(Version version) - { - if (characterCountBitsForVersions == null) - { - throw new ArgumentException("Character count doesn't apply to this mode"); - } - int number = version.VersionNumber; - int offset; - if (number <= 9) - { - offset = 0; - } - else if (number <= 26) - { - offset = 1; - } - else - { - offset = 2; - } - return characterCountBitsForVersions[offset]; - } - - /// - /// Gets the bits. - /// - public int Bits - { - get - { - return bits; - } - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - return name; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/QRCodeDecoderMetaData.cs b/zxing.core/xx/qrcode/decoder/QRCodeDecoderMetaData.cs deleted file mode 100644 index db12696..0000000 --- a/zxing.core/xx/qrcode/decoder/QRCodeDecoderMetaData.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2013 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.QrCode.Internal -{ - /// - /// Meta-data container for QR Code decoding. Instances of this class may be used to convey information back to the - /// decoding caller. Callers are expected to process this. - /// - public sealed class QRCodeDecoderMetaData - { - private readonly bool mirrored; - - /// - /// Initializes a new instance of the class. - /// - /// if set to true [mirrored]. - public QRCodeDecoderMetaData(bool mirrored) - { - this.mirrored = mirrored; - } - - /// - /// true if the QR Code was mirrored. - /// - public bool IsMirrored - { - get { return mirrored; } - } - - /// - /// Apply the result points' order correction due to mirroring. - /// - /// Array of points to apply mirror correction to. - public void applyMirroredCorrection(ResultPoint[] points) - { - if (!mirrored || points == null || points.Length < 3) - { - return; - } - ResultPoint bottomLeft = points[0]; - points[0] = points[2]; - points[2] = bottomLeft; - // No need to 'fix' top-left and alignment pattern. - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/decoder/Version.cs b/zxing.core/xx/qrcode/decoder/Version.cs deleted file mode 100644 index e39ab71..0000000 --- a/zxing.core/xx/qrcode/decoder/Version.cs +++ /dev/null @@ -1,685 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -using ZXing.Common; - -namespace ZXing.QrCode.Internal -{ - /// - /// See ISO 18004:2006 Annex D - /// - /// Sean Owen - public sealed class Version - { - /// See ISO 18004:2006 Annex D. - /// Element i represents the raw version bits that specify version i + 7 - /// - private static readonly int[] VERSION_DECODE_INFO = new[] - { - 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, - 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, - 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, - 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, - 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, - 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, - 0x2542E, 0x26A64, 0x27541, 0x28C69 - }; - - private static readonly Version[] VERSIONS = buildVersions(); - - private readonly int versionNumber; - private readonly int[] alignmentPatternCenters; - private readonly ECBlocks[] ecBlocks; - private readonly int totalCodewords; - - private Version(int versionNumber, int[] alignmentPatternCenters, params ECBlocks[] ecBlocks) - { - this.versionNumber = versionNumber; - this.alignmentPatternCenters = alignmentPatternCenters; - this.ecBlocks = ecBlocks; - int total = 0; - int ecCodewords = ecBlocks[0].ECCodewordsPerBlock; - ECB[] ecbArray = ecBlocks[0].getECBlocks(); - foreach (var ecBlock in ecbArray) - { - total += ecBlock.Count * (ecBlock.DataCodewords + ecCodewords); - } - this.totalCodewords = total; - } - - /// - /// Gets the version number. - /// - public int VersionNumber - { - get - { - return versionNumber; - } - - } - - /// - /// Gets the alignment pattern centers. - /// - public int[] AlignmentPatternCenters - { - get - { - return alignmentPatternCenters; - } - - } - - /// - /// Gets the total codewords. - /// - public int TotalCodewords - { - get - { - return totalCodewords; - } - - } - - /// - /// Gets the dimension for version. - /// - public int DimensionForVersion - { - get - { - return 17 + 4 * versionNumber; - } - - } - - /// - /// Gets the EC blocks for level. - /// - /// The ec level. - /// - public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) - { - return ecBlocks[ecLevel.ordinal()]; - } - - ///

Deduces version information purely from QR Code dimensions.

- /// - ///
- /// dimension in modules - /// - /// for a QR Code of that dimension or null - public static Version getProvisionalVersionForDimension(int dimension) - { - if (dimension % 4 != 1) - { - return null; - } - try - { - return getVersionForNumber((dimension - 17) >> 2); - } - catch (ArgumentException) - { - return null; - } - } - - /// - /// Gets the version for number. - /// - /// The version number. - /// - public static Version getVersionForNumber(int versionNumber) - { - if (versionNumber < 1 || versionNumber > 40) - { - throw new ArgumentException(); - } - return VERSIONS[versionNumber - 1]; - } - - internal static Version decodeVersionInformation(int versionBits) - { - int bestDifference = Int32.MaxValue; - int bestVersion = 0; - for (int i = 0; i < VERSION_DECODE_INFO.Length; i++) - { - int targetVersion = VERSION_DECODE_INFO[i]; - // Do the version info bits match exactly? done. - if (targetVersion == versionBits) - { - return getVersionForNumber(i + 7); - } - // Otherwise see if this is the closest to a real version info bit string - // we have seen so far - int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion); - if (bitsDifference < bestDifference) - { - bestVersion = i + 7; - bestDifference = bitsDifference; - } - } - // We can tolerate up to 3 bits of error since no two version info codewords will - // differ in less than 8 bits. - if (bestDifference <= 3) - { - return getVersionForNumber(bestVersion); - } - // If we didn't find a close enough match, fail - return null; - } - - /// See ISO 18004:2006 Annex E - internal BitMatrix buildFunctionPattern() - { - int dimension = DimensionForVersion; - BitMatrix bitMatrix = new BitMatrix(dimension); - - // Top left finder pattern + separator + format - bitMatrix.setRegion(0, 0, 9, 9); - // Top right finder pattern + separator + format - bitMatrix.setRegion(dimension - 8, 0, 8, 9); - // Bottom left finder pattern + separator + format - bitMatrix.setRegion(0, dimension - 8, 9, 8); - - // Alignment patterns - int max = alignmentPatternCenters.Length; - for (int x = 0; x < max; x++) - { - int i = alignmentPatternCenters[x] - 2; - for (int y = 0; y < max; y++) - { - if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) - { - // No alignment patterns near the three finder paterns - continue; - } - bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5); - } - } - - // Vertical timing pattern - bitMatrix.setRegion(6, 9, 1, dimension - 17); - // Horizontal timing pattern - bitMatrix.setRegion(9, 6, dimension - 17, 1); - - if (versionNumber > 6) - { - // Version info, top right - bitMatrix.setRegion(dimension - 11, 0, 3, 6); - // Version info, bottom left - bitMatrix.setRegion(0, dimension - 11, 6, 3); - } - - return bitMatrix; - } - - ///

Encapsulates a set of error-correction blocks in one symbol version. Most versions will - /// use blocks of differing sizes within one version, so, this encapsulates the parameters for - /// each set of blocks. It also holds the number of error-correction codewords per block since it - /// will be the same across all blocks within one version.

- ///
- public sealed class ECBlocks - { - private readonly int ecCodewordsPerBlock; - private readonly ECB[] ecBlocks; - - internal ECBlocks(int ecCodewordsPerBlock, params ECB[] ecBlocks) - { - this.ecCodewordsPerBlock = ecCodewordsPerBlock; - this.ecBlocks = ecBlocks; - } - - /// - /// Gets the EC codewords per block. - /// - public int ECCodewordsPerBlock - { - get - { - return ecCodewordsPerBlock; - } - } - - /// - /// Gets the num blocks. - /// - public int NumBlocks - { - get - { - int total = 0; - foreach (var ecBlock in ecBlocks) - { - total += ecBlock.Count; - } - return total; - } - } - - /// - /// Gets the total EC codewords. - /// - public int TotalECCodewords - { - get - { - return ecCodewordsPerBlock * NumBlocks; - } - } - - /// - /// Gets the EC blocks. - /// - /// - public ECB[] getECBlocks() - { - return ecBlocks; - } - } - - ///

Encapsualtes the parameters for one error-correction block in one symbol version. - /// This includes the number of data codewords, and the number of times a block with these - /// parameters is used consecutively in the QR code version's format.

- ///
- public sealed class ECB - { - private readonly int count; - private readonly int dataCodewords; - - internal ECB(int count, int dataCodewords) - { - this.count = count; - this.dataCodewords = dataCodewords; - } - - /// - /// Gets the count. - /// - public int Count - { - get - { - return count; - } - - } - /// - /// Gets the data codewords. - /// - public int DataCodewords - { - get - { - return dataCodewords; - } - - } - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - return Convert.ToString(versionNumber); - } - - /// See ISO 18004:2006 6.5.1 Table 9 - private static Version[] buildVersions() - { - return new Version[] - { - new Version(1, new int[] {}, - new ECBlocks(7, new ECB(1, 19)), - new ECBlocks(10, new ECB(1, 16)), - new ECBlocks(13, new ECB(1, 13)), - new ECBlocks(17, new ECB(1, 9))), - new Version(2, new int[] {6, 18}, - new ECBlocks(10, new ECB(1, 34)), - new ECBlocks(16, new ECB(1, 28)), - new ECBlocks(22, new ECB(1, 22)), - new ECBlocks(28, new ECB(1, 16))), - new Version(3, new int[] {6, 22}, - new ECBlocks(15, new ECB(1, 55)), - new ECBlocks(26, new ECB(1, 44)), - new ECBlocks(18, new ECB(2, 17)), - new ECBlocks(22, new ECB(2, 13))), - new Version(4, new int[] {6, 26}, - new ECBlocks(20, new ECB(1, 80)), - new ECBlocks(18, new ECB(2, 32)), - new ECBlocks(26, new ECB(2, 24)), - new ECBlocks(16, new ECB(4, 9))), - new Version(5, new int[] {6, 30}, - new ECBlocks(26, new ECB(1, 108)), - new ECBlocks(24, new ECB(2, 43)), - new ECBlocks(18, new ECB(2, 15), - new ECB(2, 16)), - new ECBlocks(22, new ECB(2, 11), - new ECB(2, 12))), - new Version(6, new int[] {6, 34}, - new ECBlocks(18, new ECB(2, 68)), - new ECBlocks(16, new ECB(4, 27)), - new ECBlocks(24, new ECB(4, 19)), - new ECBlocks(28, new ECB(4, 15))), - new Version(7, new int[] {6, 22, 38}, - new ECBlocks(20, new ECB(2, 78)), - new ECBlocks(18, new ECB(4, 31)), - new ECBlocks(18, new ECB(2, 14), - new ECB(4, 15)), - new ECBlocks(26, new ECB(4, 13), - new ECB(1, 14))), - new Version(8, new int[] {6, 24, 42}, - new ECBlocks(24, new ECB(2, 97)), - new ECBlocks(22, new ECB(2, 38), - new ECB(2, 39)), - new ECBlocks(22, new ECB(4, 18), - new ECB(2, 19)), - new ECBlocks(26, new ECB(4, 14), - new ECB(2, 15))), - new Version(9, new int[] {6, 26, 46}, - new ECBlocks(30, new ECB(2, 116)), - new ECBlocks(22, new ECB(3, 36), - new ECB(2, 37)), - new ECBlocks(20, new ECB(4, 16), - new ECB(4, 17)), - new ECBlocks(24, new ECB(4, 12), - new ECB(4, 13))), - new Version(10, new int[] {6, 28, 50}, - new ECBlocks(18, new ECB(2, 68), - new ECB(2, 69)), - new ECBlocks(26, new ECB(4, 43), - new ECB(1, 44)), - new ECBlocks(24, new ECB(6, 19), - new ECB(2, 20)), - new ECBlocks(28, new ECB(6, 15), - new ECB(2, 16))), - new Version(11, new int[] {6, 30, 54}, - new ECBlocks(20, new ECB(4, 81)), - new ECBlocks(30, new ECB(1, 50), - new ECB(4, 51)), - new ECBlocks(28, new ECB(4, 22), - new ECB(4, 23)), - new ECBlocks(24, new ECB(3, 12), - new ECB(8, 13))), - new Version(12, new int[] {6, 32, 58}, - new ECBlocks(24, new ECB(2, 92), - new ECB(2, 93)), - new ECBlocks(22, new ECB(6, 36), - new ECB(2, 37)), - new ECBlocks(26, new ECB(4, 20), - new ECB(6, 21)), - new ECBlocks(28, new ECB(7, 14), - new ECB(4, 15))), - new Version(13, new int[] {6, 34, 62}, - new ECBlocks(26, new ECB(4, 107)), - new ECBlocks(22, new ECB(8, 37), - new ECB(1, 38)), - new ECBlocks(24, new ECB(8, 20), - new ECB(4, 21)), - new ECBlocks(22, new ECB(12, 11), - new ECB(4, 12))), - new Version(14, new int[] {6, 26, 46, 66}, - new ECBlocks(30, new ECB(3, 115), - new ECB(1, 116)), - new ECBlocks(24, new ECB(4, 40), - new ECB(5, 41)), - new ECBlocks(20, new ECB(11, 16), - new ECB(5, 17)), - new ECBlocks(24, new ECB(11, 12), - new ECB(5, 13))), - new Version(15, new int[] {6, 26, 48, 70}, - new ECBlocks(22, new ECB(5, 87), - new ECB(1, 88)), - new ECBlocks(24, new ECB(5, 41), - new ECB(5, 42)), - new ECBlocks(30, new ECB(5, 24), - new ECB(7, 25)), - new ECBlocks(24, new ECB(11, 12), - new ECB(7, 13))), - new Version(16, new int[] {6, 26, 50, 74}, - new ECBlocks(24, new ECB(5, 98), - new ECB(1, 99)), - new ECBlocks(28, new ECB(7, 45), - new ECB(3, 46)), - new ECBlocks(24, new ECB(15, 19), - new ECB(2, 20)), - new ECBlocks(30, new ECB(3, 15), - new ECB(13, 16))), - new Version(17, new int[] {6, 30, 54, 78}, - new ECBlocks(28, new ECB(1, 107), - new ECB(5, 108)), - new ECBlocks(28, new ECB(10, 46), - new ECB(1, 47)), - new ECBlocks(28, new ECB(1, 22), - new ECB(15, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(17, 15))), - new Version(18, new int[] {6, 30, 56, 82}, - new ECBlocks(30, new ECB(5, 120), - new ECB(1, 121)), - new ECBlocks(26, new ECB(9, 43), - new ECB(4, 44)), - new ECBlocks(28, new ECB(17, 22), - new ECB(1, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(19, 15))), - new Version(19, new int[] {6, 30, 58, 86}, - new ECBlocks(28, new ECB(3, 113), - new ECB(4, 114)), - new ECBlocks(26, new ECB(3, 44), - new ECB(11, 45)), - new ECBlocks(26, new ECB(17, 21), - new ECB(4, 22)), - new ECBlocks(26, new ECB(9, 13), - new ECB(16, 14))), - new Version(20, new int[] {6, 34, 62, 90}, - new ECBlocks(28, new ECB(3, 107), - new ECB(5, 108)), - new ECBlocks(26, new ECB(3, 41), - new ECB(13, 42)), - new ECBlocks(30, new ECB(15, 24), - new ECB(5, 25)), - new ECBlocks(28, new ECB(15, 15), - new ECB(10, 16))), - new Version(21, new int[] {6, 28, 50, 72, 94}, - new ECBlocks(28, new ECB(4, 116), - new ECB(4, 117)), - new ECBlocks(26, new ECB(17, 42)), - new ECBlocks(28, new ECB(17, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(19, 16), - new ECB(6, 17))), - new Version(22, new int[] {6, 26, 50, 74, 98}, - new ECBlocks(28, new ECB(2, 111), - new ECB(7, 112)), - new ECBlocks(28, new ECB(17, 46)), - new ECBlocks(30, new ECB(7, 24), - new ECB(16, 25)), - new ECBlocks(24, new ECB(34, 13))), - new Version(23, new int[] {6, 30, 54, 78, 102}, - new ECBlocks(30, new ECB(4, 121), - new ECB(5, 122)), - new ECBlocks(28, new ECB(4, 47), - new ECB(14, 48)), - new ECBlocks(30, new ECB(11, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(16, 15), - new ECB(14, 16))), - new Version(24, new int[] {6, 28, 54, 80, 106}, - new ECBlocks(30, new ECB(6, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(6, 45), - new ECB(14, 46)), - new ECBlocks(30, new ECB(11, 24), - new ECB(16, 25)), - new ECBlocks(30, new ECB(30, 16), - new ECB(2, 17))), - new Version(25, new int[] {6, 32, 58, 84, 110}, - new ECBlocks(26, new ECB(8, 106), - new ECB(4, 107)), - new ECBlocks(28, new ECB(8, 47), - new ECB(13, 48)), - new ECBlocks(30, new ECB(7, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(13, 16))), - new Version(26, new int[] {6, 30, 58, 86, 114}, - new ECBlocks(28, new ECB(10, 114), - new ECB(2, 115)), - new ECBlocks(28, new ECB(19, 46), - new ECB(4, 47)), - new ECBlocks(28, new ECB(28, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(33, 16), - new ECB(4, 17))), - new Version(27, new int[] {6, 34, 62, 90, 118}, - new ECBlocks(30, new ECB(8, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(22, 45), - new ECB(3, 46)), - new ECBlocks(30, new ECB(8, 23), - new ECB(26, 24)), - new ECBlocks(30, new ECB(12, 15), - new ECB(28, 16))), - new Version(28, new int[] {6, 26, 50, 74, 98, 122}, - new ECBlocks(30, new ECB(3, 117), - new ECB(10, 118)), - new ECBlocks(28, new ECB(3, 45), - new ECB(23, 46)), - new ECBlocks(30, new ECB(4, 24), - new ECB(31, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(31, 16))), - new Version(29, new int[] {6, 30, 54, 78, 102, 126}, - new ECBlocks(30, new ECB(7, 116), - new ECB(7, 117)), - new ECBlocks(28, new ECB(21, 45), - new ECB(7, 46)), - new ECBlocks(30, new ECB(1, 23), - new ECB(37, 24)), - new ECBlocks(30, new ECB(19, 15), - new ECB(26, 16))), - new Version(30, new int[] {6, 26, 52, 78, 104, 130}, - new ECBlocks(30, new ECB(5, 115), - new ECB(10, 116)), - new ECBlocks(28, new ECB(19, 47), - new ECB(10, 48)), - new ECBlocks(30, new ECB(15, 24), - new ECB(25, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(25, 16))), - new Version(31, new int[] {6, 30, 56, 82, 108, 134}, - new ECBlocks(30, new ECB(13, 115), - new ECB(3, 116)), - new ECBlocks(28, new ECB(2, 46), - new ECB(29, 47)), - new ECBlocks(30, new ECB(42, 24), - new ECB(1, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(28, 16))), - new Version(32, new int[] {6, 34, 60, 86, 112, 138}, - new ECBlocks(30, new ECB(17, 115)), - new ECBlocks(28, new ECB(10, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(10, 24), - new ECB(35, 25)), - new ECBlocks(30, new ECB(19, 15), - new ECB(35, 16))), - new Version(33, new int[] {6, 30, 58, 86, 114, 142}, - new ECBlocks(30, new ECB(17, 115), - new ECB(1, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(21, 47)), - new ECBlocks(30, new ECB(29, 24), - new ECB(19, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(46, 16))), - new Version(34, new int[] {6, 34, 62, 90, 118, 146}, - new ECBlocks(30, new ECB(13, 115), - new ECB(6, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(44, 24), - new ECB(7, 25)), - new ECBlocks(30, new ECB(59, 16), - new ECB(1, 17))), - new Version(35, new int[] {6, 30, 54, 78, 102, 126, 150}, - new ECBlocks(30, new ECB(12, 121), - new ECB(7, 122)), - new ECBlocks(28, new ECB(12, 47), - new ECB(26, 48)), - new ECBlocks(30, new ECB(39, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(41, 16))), - new Version(36, new int[] {6, 24, 50, 76, 102, 128, 154}, - new ECBlocks(30, new ECB(6, 121), - new ECB(14, 122)), - new ECBlocks(28, new ECB(6, 47), - new ECB(34, 48)), - new ECBlocks(30, new ECB(46, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(2, 15), - new ECB(64, 16))), - new Version(37, new int[] {6, 28, 54, 80, 106, 132, 158}, - new ECBlocks(30, new ECB(17, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(29, 46), - new ECB(14, 47)), - new ECBlocks(30, new ECB(49, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(24, 15), - new ECB(46, 16))), - new Version(38, new int[] {6, 32, 58, 84, 110, 136, 162}, - new ECBlocks(30, new ECB(4, 122), - new ECB(18, 123)), - new ECBlocks(28, new ECB(13, 46), - new ECB(32, 47)), - new ECBlocks(30, new ECB(48, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(42, 15), - new ECB(32, 16))), - new Version(39, new int[] {6, 26, 54, 82, 110, 138, 166}, - new ECBlocks(30, new ECB(20, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(40, 47), - new ECB(7, 48)), - new ECBlocks(30, new ECB(43, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(10, 15), - new ECB(67, 16))), - new Version(40, new int[] {6, 30, 58, 86, 114, 142, 170}, - new ECBlocks(30, new ECB(19, 118), - new ECB(6, 119)), - new ECBlocks(28, new ECB(18, 47), - new ECB(31, 48)), - new ECBlocks(30, new ECB(34, 24), - new ECB(34, 25)), - new ECBlocks(30, new ECB(20, 15), - new ECB(61, 16))) - }; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/detector/AlignmentPattern.cs b/zxing.core/xx/qrcode/detector/AlignmentPattern.cs deleted file mode 100644 index 7439897..0000000 --- a/zxing.core/xx/qrcode/detector/AlignmentPattern.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.QrCode.Internal -{ - ///

Encapsulates an alignment pattern, which are the smaller square patterns found in - /// all but the simplest QR Codes.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - public sealed class AlignmentPattern : ResultPoint - { - private float estimatedModuleSize; - - internal AlignmentPattern(float posX, float posY, float estimatedModuleSize) - : base(posX, posY) - { - this.estimatedModuleSize = estimatedModuleSize; - } - - ///

Determines if this alignment pattern "about equals" an alignment pattern at the stated - /// position and size -- meaning, it is at nearly the same center with nearly the same size.

- ///
- internal bool aboutEquals(float moduleSize, float i, float j) - { - if (Math.Abs(i - Y) <= moduleSize && Math.Abs(j - X) <= moduleSize) - { - float moduleSizeDiff = Math.Abs(moduleSize - estimatedModuleSize); - return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize; - } - return false; - } - - /// - /// Combines this object's current estimate of a finder pattern position and module size - /// with a new estimate. It returns a new {@code FinderPattern} containing an average of the two. - /// - /// The i. - /// The j. - /// New size of the module. - /// - internal AlignmentPattern combineEstimate(float i, float j, float newModuleSize) - { - float combinedX = (X + j) / 2.0f; - float combinedY = (Y + i) / 2.0f; - float combinedModuleSize = (estimatedModuleSize + newModuleSize) / 2.0f; - return new AlignmentPattern(combinedX, combinedY, combinedModuleSize); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/detector/AlignmentPatternFinder.cs b/zxing.core/xx/qrcode/detector/AlignmentPatternFinder.cs deleted file mode 100644 index 362750d..0000000 --- a/zxing.core/xx/qrcode/detector/AlignmentPatternFinder.cs +++ /dev/null @@ -1,324 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.QrCode.Internal -{ - ///

This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder - /// patterns but are smaller and appear at regular intervals throughout the image.

- /// - ///

At the moment this only looks for the bottom-right alignment pattern.

- /// - ///

This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied, - /// pasted and stripped down here for maximum performance but does unfortunately duplicate - /// some code.

- /// - ///

This class is thread-safe but not reentrant. Each thread must allocate its own object.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - sealed class AlignmentPatternFinder - { - private readonly BitMatrix image; - private readonly IList possibleCenters; - private readonly int startX; - private readonly int startY; - private readonly int width; - private readonly int height; - private readonly float moduleSize; - private readonly int[] crossCheckStateCount; - private readonly ResultPointCallback resultPointCallback; - - ///

Creates a finder that will look in a portion of the whole image.

- /// - ///
- /// image to search - /// - /// left column from which to start searching - /// - /// top row from which to start searching - /// - /// width of region to search - /// - /// height of region to search - /// - /// estimated module size so far - /// - internal AlignmentPatternFinder(BitMatrix image, int startX, int startY, int width, int height, float moduleSize, ResultPointCallback resultPointCallback) - { - this.image = image; - this.possibleCenters = new List(5); - this.startX = startX; - this.startY = startY; - this.width = width; - this.height = height; - this.moduleSize = moduleSize; - this.crossCheckStateCount = new int[3]; - this.resultPointCallback = resultPointCallback; - } - - ///

This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since - /// it's pretty performance-critical and so is written to be fast foremost.

- /// - ///
- /// {@link AlignmentPattern} if found - /// - internal AlignmentPattern find() - { - int startX = this.startX; - int height = this.height; - int maxJ = startX + width; - int middleI = startY + (height >> 1); - // We are looking for black/white/black modules in 1:1:1 ratio; - // this tracks the number of black/white/black modules seen so far - int[] stateCount = new int[3]; - for (int iGen = 0; iGen < height; iGen++) - { - // Search from middle outwards - int i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1)); - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - int j = startX; - // Burn off leading white pixels before anything else; if we start in the middle of - // a white run, it doesn't make sense to count its length, since we don't know if the - // white run continued to the left of the start point - while (j < maxJ && !image[j, i]) - { - j++; - } - int currentState = 0; - while (j < maxJ) - { - if (image[j, i]) - { - // Black pixel - if (currentState == 1) - { - // Counting black pixels - stateCount[currentState]++; - } - else - { - // Counting white pixels - if (currentState == 2) - { - // A winner? - if (foundPatternCross(stateCount)) - { - // Yes - AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, j); - if (confirmed != null) - { - return confirmed; - } - } - stateCount[0] = stateCount[2]; - stateCount[1] = 1; - stateCount[2] = 0; - currentState = 1; - } - else - { - stateCount[++currentState]++; - } - } - } - else - { - // White pixel - if (currentState == 1) - { - // Counting black pixels - currentState++; - } - stateCount[currentState]++; - } - j++; - } - if (foundPatternCross(stateCount)) - { - AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, maxJ); - if (confirmed != null) - { - return confirmed; - } - } - } - - // Hmm, nothing we saw was observed and confirmed twice. If we had - // any guess at all, return it. - if (possibleCenters.Count != 0) - { - return possibleCenters[0]; - } - - return null; - } - - /// Given a count of black/white/black pixels just seen and an end position, - /// figures the location of the center of this black/white/black run. - /// - private static float? centerFromEnd(int[] stateCount, int end) - { - var result = (end - stateCount[2]) - stateCount[1] / 2.0f; - if (Single.IsNaN(result)) - return null; - return result; - } - - /// count of black/white/black pixels just read - /// - /// true iff the proportions of the counts is close enough to the 1/1/1 ratios - /// used by alignment patterns to be considered a match - /// - private bool foundPatternCross(int[] stateCount) - { - float maxVariance = moduleSize / 2.0f; - for (int i = 0; i < 3; i++) - { - if (Math.Abs(moduleSize - stateCount[i]) >= maxVariance) - { - return false; - } - } - return true; - } - - /// - ///

After a horizontal scan finds a potential alignment pattern, this method - /// "cross-checks" by scanning down vertically through the center of the possible - /// alignment pattern to see if the same proportion is detected.

- ///
- /// row where an alignment pattern was detected - /// center of the section that appears to cross an alignment pattern - /// maximum reasonable number of modules that should be - /// observed in any reading state, based on the results of the horizontal scan - /// The original state count total. - /// - /// vertical center of alignment pattern, or null if not found - /// - private float? crossCheckVertical(int startI, int centerJ, int maxCount, int originalStateCountTotal) - { - int maxI = image.Height; - int[] stateCount = crossCheckStateCount; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - - // Start counting up from center - int i = startI; - while (i >= 0 && image[centerJ, i] && stateCount[1] <= maxCount) - { - stateCount[1]++; - i--; - } - // If already too many modules in this state or ran off the edge: - if (i < 0 || stateCount[1] > maxCount) - { - return null; - } - while (i >= 0 && !image[centerJ, i] && stateCount[0] <= maxCount) - { - stateCount[0]++; - i--; - } - if (stateCount[0] > maxCount) - { - return null; - } - - // Now also count down from center - i = startI + 1; - while (i < maxI && image[centerJ, i] && stateCount[1] <= maxCount) - { - stateCount[1]++; - i++; - } - if (i == maxI || stateCount[1] > maxCount) - { - return null; - } - while (i < maxI && !image[centerJ, i] && stateCount[2] <= maxCount) - { - stateCount[2]++; - i++; - } - if (stateCount[2] > maxCount) - { - return null; - } - - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; - if (5 * Math.Abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) - { - return null; - } - - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : null; - } - - ///

This is called when a horizontal scan finds a possible alignment pattern. It will - /// cross check with a vertical scan, and if successful, will see if this pattern had been - /// found on a previous horizontal scan. If so, we consider it confirmed and conclude we have - /// found the alignment pattern.

- /// - ///
- /// reading state module counts from horizontal scan - /// - /// row where alignment pattern may be found - /// - /// end of possible alignment pattern in row - /// - /// {@link AlignmentPattern} if we have found the same pattern twice, or null if not - /// - private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) - { - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2]; - float? centerJ = centerFromEnd(stateCount, j); - if (centerJ == null) - return null; - float? centerI = crossCheckVertical(i, (int)centerJ, 2 * stateCount[1], stateCountTotal); - if (centerI != null) - { - float estimatedModuleSize = (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f; - foreach (var center in possibleCenters) - { - // Look for about the same center and module size: - if (center.aboutEquals(estimatedModuleSize, centerI.Value, centerJ.Value)) - { - return center.combineEstimate(centerI.Value, centerJ.Value, estimatedModuleSize); - } - } - // Hadn't found this before; save it - var point = new AlignmentPattern(centerJ.Value, centerI.Value, estimatedModuleSize); - possibleCenters.Add(point); - if (resultPointCallback != null) - { - resultPointCallback(point); - } - } - return null; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/detector/Detector.cs b/zxing.core/xx/qrcode/detector/Detector.cs deleted file mode 100644 index 7105f8e..0000000 --- a/zxing.core/xx/qrcode/detector/Detector.cs +++ /dev/null @@ -1,434 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -using ZXing.Common; -using ZXing.Common.Detector; - -namespace ZXing.QrCode.Internal -{ - /// - ///

Encapsulates logic that can detect a QR Code in an image, even if the QR Code - /// is rotated or skewed, or partially obscured.

- ///
- /// Sean Owen - public class Detector - { - private readonly BitMatrix image; - private ResultPointCallback resultPointCallback; - - /// - /// Initializes a new instance of the class. - /// - /// The image. - public Detector(BitMatrix image) - { - this.image = image; - } - - /// - /// Gets the image. - /// - virtual protected internal BitMatrix Image - { - get - { - return image; - } - } - - /// - /// Gets the result point callback. - /// - virtual protected internal ResultPointCallback ResultPointCallback - { - get - { - return resultPointCallback; - } - } - - /// - ///

Detects a QR Code in an image.

- ///
- /// - /// encapsulating results of detecting a QR Code - /// - public virtual DetectorResult detect() - { - return detect(null); - } - - /// - ///

Detects a QR Code in an image.

- ///
- /// optional hints to detector - /// - /// encapsulating results of detecting a QR Code - /// - public virtual DetectorResult detect(IDictionary hints) - { - resultPointCallback = hints == null || !hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK) ? null : (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK]; - - FinderPatternFinder finder = new FinderPatternFinder(image, resultPointCallback); - FinderPatternInfo info = finder.find(hints); - if (info == null) - return null; - - return processFinderPatternInfo(info); - } - - /// - /// Processes the finder pattern info. - /// - /// The info. - /// - protected internal virtual DetectorResult processFinderPatternInfo(FinderPatternInfo info) - { - FinderPattern topLeft = info.TopLeft; - FinderPattern topRight = info.TopRight; - FinderPattern bottomLeft = info.BottomLeft; - - float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft); - if (moduleSize < 1.0f) - { - return null; - } - int dimension; - if (!computeDimension(topLeft, topRight, bottomLeft, moduleSize, out dimension)) - return null; - Internal.Version provisionalVersion = Internal.Version.getProvisionalVersionForDimension(dimension); - if (provisionalVersion == null) - return null; - int modulesBetweenFPCenters = provisionalVersion.DimensionForVersion - 7; - - AlignmentPattern alignmentPattern = null; - // Anything above version 1 has an alignment pattern - if (provisionalVersion.AlignmentPatternCenters.Length > 0) - { - - // Guess where a "bottom right" finder pattern would have been - float bottomRightX = topRight.X - topLeft.X + bottomLeft.X; - float bottomRightY = topRight.Y - topLeft.Y + bottomLeft.Y; - - // Estimate that alignment pattern is closer by 3 modules - // from "bottom right" to known top left location - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters; - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int estAlignmentX = (int)(topLeft.X + correctionToTopLeft * (bottomRightX - topLeft.X)); - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int estAlignmentY = (int)(topLeft.Y + correctionToTopLeft * (bottomRightY - topLeft.Y)); - - // Kind of arbitrary -- expand search radius before giving up - for (int i = 4; i <= 16; i <<= 1) - { - alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i); - if (alignmentPattern == null) - continue; - break; - } - // If we didn't find alignment pattern... well try anyway without it - } - - PerspectiveTransform transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); - - BitMatrix bits = sampleGrid(image, transform, dimension); - if (bits == null) - return null; - - ResultPoint[] points; - if (alignmentPattern == null) - { - points = new ResultPoint[] { bottomLeft, topLeft, topRight }; - } - else - { - points = new ResultPoint[] { bottomLeft, topLeft, topRight, alignmentPattern }; - } - return new DetectorResult(bits, points); - } - - private static PerspectiveTransform createTransform(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, ResultPoint alignmentPattern, int dimension) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - float dimMinusThree = (float)dimension - 3.5f; - float bottomRightX; - float bottomRightY; - float sourceBottomRightX; - float sourceBottomRightY; - if (alignmentPattern != null) - { - bottomRightX = alignmentPattern.X; - bottomRightY = alignmentPattern.Y; - sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f; - } - else - { - // Don't have an alignment pattern, just make up the bottom-right point - bottomRightX = (topRight.X - topLeft.X) + bottomLeft.X; - bottomRightY = (topRight.Y - topLeft.Y) + bottomLeft.Y; - sourceBottomRightX = sourceBottomRightY = dimMinusThree; - } - - return PerspectiveTransform.quadrilateralToQuadrilateral( - 3.5f, - 3.5f, - dimMinusThree, - 3.5f, - sourceBottomRightX, - sourceBottomRightY, - 3.5f, - dimMinusThree, - topLeft.X, - topLeft.Y, - topRight.X, - topRight.Y, - bottomRightX, - bottomRightY, - bottomLeft.X, - bottomLeft.Y); - } - - private static BitMatrix sampleGrid(BitMatrix image, PerspectiveTransform transform, int dimension) - { - GridSampler sampler = GridSampler.Instance; - return sampler.sampleGrid(image, dimension, dimension, transform); - } - - ///

Computes the dimension (number of modules on a size) of the QR Code based on the position - /// of the finder patterns and estimated module size.

- ///
- private static bool computeDimension(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft, float moduleSize, out int dimension) - { - int tltrCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, topRight) / moduleSize); - int tlblCentersDimension = MathUtils.round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize); - dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7; - switch (dimension & 0x03) - { - // mod 4 - case 0: - dimension++; - break; - // 1? do nothing - case 2: - dimension--; - break; - case 3: - return true; - } - return true; - } - - /// - ///

Computes an average estimated module size based on estimated derived from the positions - /// of the three finder patterns.

- ///
- /// detected top-left finder pattern center - /// detected top-right finder pattern center - /// detected bottom-left finder pattern center - /// estimated module size - protected internal virtual float calculateModuleSize(ResultPoint topLeft, ResultPoint topRight, ResultPoint bottomLeft) - { - // Take the average - return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f; - } - - ///

Estimates module size based on two finder patterns -- it uses - /// {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the - /// width of each, measuring along the axis between their centers.

- ///
- private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern.X, (int)pattern.Y, (int)otherPattern.X, (int)otherPattern.Y); - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern.X, (int)otherPattern.Y, (int)pattern.X, (int)pattern.Y); - if (Single.IsNaN(moduleSizeEst1)) - { - return moduleSizeEst2 / 7.0f; - } - if (Single.IsNaN(moduleSizeEst2)) - { - return moduleSizeEst1 / 7.0f; - } - // Average them, and divide by 7 since we've counted the width of 3 black modules, - // and 1 white and 1 black module on either side. Ergo, divide sum by 14. - return (moduleSizeEst1 + moduleSizeEst2) / 14.0f; - } - - /// See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of - /// a finder pattern by looking for a black-white-black run from the center in the direction - /// of another point (another finder pattern center), and in the opposite direction too. - /// - private float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) - { - - float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY); - - // Now count other way -- don't run off image though of course - float scale = 1.0f; - int otherToX = fromX - (toX - fromX); - if (otherToX < 0) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - scale = (float)fromX / (float)(fromX - otherToX); - otherToX = 0; - } - else if (otherToX >= image.Width) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - scale = (float)(image.Width - 1 - fromX) / (float)(otherToX - fromX); - otherToX = image.Width - 1; - } - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int otherToY = (int)(fromY - (toY - fromY) * scale); - - scale = 1.0f; - if (otherToY < 0) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - scale = (float)fromY / (float)(fromY - otherToY); - otherToY = 0; - } - else if (otherToY >= image.Height) - { - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - scale = (float)(image.Height - 1 - fromY) / (float)(otherToY - fromY); - otherToY = image.Height - 1; - } - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - otherToX = (int)(fromX + (otherToX - fromX) * scale); - - result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY); - return result - 1.0f; // -1 because we counted the middle pixel twice - } - - ///

This method traces a line from a point in the image, in the direction towards another point. - /// It begins in a black region, and keeps going until it finds white, then black, then white again. - /// It reports the distance from the start to this point.

- /// - ///

This is used when figuring out how wide a finder pattern is, when the finder pattern - /// may be skewed or rotated.

- ///
- private float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) - { - // Mild variant of Bresenham's algorithm; - // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm - bool steep = Math.Abs(toY - fromY) > Math.Abs(toX - fromX); - if (steep) - { - int temp = fromX; - fromX = fromY; - fromY = temp; - temp = toX; - toX = toY; - toY = temp; - } - - int dx = Math.Abs(toX - fromX); - int dy = Math.Abs(toY - fromY); - int error = -dx >> 1; - int xstep = fromX < toX ? 1 : -1; - int ystep = fromY < toY ? 1 : -1; - - // In black pixels, looking for white, first or second time. - int state = 0; - // Loop up until x == toX, but not beyond - int xLimit = toX + xstep; - for (int x = fromX, y = fromY; x != xLimit; x += xstep) - { - int realX = steep ? y : x; - int realY = steep ? x : y; - - // Does current pixel mean we have moved white to black or vice versa? - // Scanning black in state 0,2 and white in state 1, so if we find the wrong - // color, advance to next state or end if we are in state 2 already - if ((state == 1) == image[realX, realY]) - { - if (state == 2) - { - return MathUtils.distance(x, y, fromX, fromY); - } - state++; - } - error += dy; - if (error > 0) - { - if (y == toY) - { - - - break; - } - y += ystep; - error -= dx; - } - } - // Found black-white-black; give the benefit of the doubt that the next pixel outside the image - // is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a - // small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this. - if (state == 2) - { - return MathUtils.distance(toX + xstep, toY, fromX, fromY); - } - // else we didn't find even black-white-black; no estimate is really possible - return Single.NaN; - - } - - /// - ///

Attempts to locate an alignment pattern in a limited region of the image, which is - /// guessed to contain it. This method uses {@link AlignmentPattern}.

- ///
- /// estimated module size so far - /// x coordinate of center of area probably containing alignment pattern - /// y coordinate of above - /// number of pixels in all directions to search from the center - /// - /// if found, or null otherwise - /// - protected AlignmentPattern findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY, float allowanceFactor) - { - // Look for an alignment pattern (3 modules in size) around where it - // should be - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - int allowance = (int)(allowanceFactor * overallEstModuleSize); - int alignmentAreaLeftX = Math.Max(0, estAlignmentX - allowance); - int alignmentAreaRightX = Math.Min(image.Width - 1, estAlignmentX + allowance); - if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) - { - return null; - } - - int alignmentAreaTopY = Math.Max(0, estAlignmentY - allowance); - int alignmentAreaBottomY = Math.Min(image.Height - 1, estAlignmentY + allowance); - - var alignmentFinder = new AlignmentPatternFinder( - image, - alignmentAreaLeftX, - alignmentAreaTopY, - alignmentAreaRightX - alignmentAreaLeftX, - alignmentAreaBottomY - alignmentAreaTopY, - overallEstModuleSize, - resultPointCallback); - - return alignmentFinder.find(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/detector/FinderPattern.cs b/zxing.core/xx/qrcode/detector/FinderPattern.cs deleted file mode 100644 index 27c5f0f..0000000 --- a/zxing.core/xx/qrcode/detector/FinderPattern.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.QrCode.Internal -{ - /// - ///

Encapsulates a finder pattern, which are the three square patterns found in - /// the corners of QR Codes. It also encapsulates a count of similar finder patterns, - /// as a convenience to the finder's bookkeeping.

- ///
- /// Sean Owen - public sealed class FinderPattern : ResultPoint - { - private readonly float estimatedModuleSize; - private int count; - - internal FinderPattern(float posX, float posY, float estimatedModuleSize) - : this(posX, posY, estimatedModuleSize, 1) - { - this.estimatedModuleSize = estimatedModuleSize; - this.count = 1; - } - - internal FinderPattern(float posX, float posY, float estimatedModuleSize, int count) - : base(posX, posY) - { - this.estimatedModuleSize = estimatedModuleSize; - this.count = count; - } - - /// - /// Gets the size of the estimated module. - /// - /// - /// The size of the estimated module. - /// - public float EstimatedModuleSize - { - get - { - return estimatedModuleSize; - } - } - - internal int Count - { - get - { - return count; - } - } - - /* - internal void incrementCount() - { - this.count++; - } - */ - - ///

Determines if this finder pattern "about equals" a finder pattern at the stated - /// position and size -- meaning, it is at nearly the same center with nearly the same size.

- ///
- internal bool aboutEquals(float moduleSize, float i, float j) - { - if (Math.Abs(i - Y) <= moduleSize && Math.Abs(j - X) <= moduleSize) - { - float moduleSizeDiff = Math.Abs(moduleSize - estimatedModuleSize); - return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize; - - } - return false; - } - - /// - /// Combines this object's current estimate of a finder pattern position and module size - /// with a new estimate. It returns a new {@code FinderPattern} containing a weighted average - /// based on count. - /// - /// The i. - /// The j. - /// New size of the module. - /// - internal FinderPattern combineEstimate(float i, float j, float newModuleSize) - { - int combinedCount = count + 1; - float combinedX = (count * X + j) / combinedCount; - float combinedY = (count * Y + i) / combinedCount; - float combinedModuleSize = (count * estimatedModuleSize + newModuleSize) / combinedCount; - return new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/detector/FinderPatternFinder.cs b/zxing.core/xx/qrcode/detector/FinderPatternFinder.cs deleted file mode 100644 index 37462cd..0000000 --- a/zxing.core/xx/qrcode/detector/FinderPatternFinder.cs +++ /dev/null @@ -1,813 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; - -using ZXing.Common; - -namespace ZXing.QrCode.Internal -{ - /// - ///

This class attempts to find finder patterns in a QR Code. Finder patterns are the square - /// markers at three corners of a QR Code.

- /// - ///

This class is thread-safe but not reentrant. Each thread must allocate its own object. - ///

- /// Sean Owen - public class FinderPatternFinder - { - private const int CENTER_QUORUM = 2; - /// - /// 1 pixel/module times 3 modules/center - /// - protected internal const int MIN_SKIP = 3; - /// - /// support up to version 10 for mobile clients - /// - protected internal const int MAX_MODULES = 57; - private const int INTEGER_MATH_SHIFT = 8; - - private readonly BitMatrix image; - private List possibleCenters; - private bool hasSkipped; - private readonly int[] crossCheckStateCount; - private readonly ResultPointCallback resultPointCallback; - - /// - ///

Creates a finder that will search the image for three finder patterns.

- ///
- /// image to search - public FinderPatternFinder(BitMatrix image) - : this(image, null) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The image. - /// The result point callback. - public FinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) - { - this.image = image; - this.possibleCenters = new List(); - this.crossCheckStateCount = new int[5]; - this.resultPointCallback = resultPointCallback; - } - - /// - /// Gets the image. - /// - virtual protected internal BitMatrix Image - { - get - { - return image; - } - } - - /// - /// Gets the possible centers. - /// - virtual protected internal List PossibleCenters - { - get - { - return possibleCenters; - } - } - - internal virtual FinderPatternInfo find(IDictionary hints) - { - bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER); - bool pureBarcode = hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE); - int maxI = image.Height; - int maxJ = image.Width; - // We are looking for black/white/black/white/black modules in - // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far - - // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the - // image, and then account for the center being 3 modules in size. This gives the smallest - // number of pixels the center could be, so skip this often. When trying harder, look for all - // QR versions regardless of how dense they are. - int iSkip = (3 * maxI) / (4 * MAX_MODULES); - if (iSkip < MIN_SKIP || tryHarder) - { - iSkip = MIN_SKIP; - } - - bool done = false; - int[] stateCount = new int[5]; - for (int i = iSkip - 1; i < maxI && !done; i += iSkip) - { - // Get a row of black/white values - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - int currentState = 0; - for (int j = 0; j < maxJ; j++) - { - if (image[j, i]) - { - // Black pixel - if ((currentState & 1) == 1) - { - // Counting white pixels - currentState++; - } - stateCount[currentState]++; - } - else - { - // White pixel - if ((currentState & 1) == 0) - { - // Counting black pixels - if (currentState == 4) - { - // A winner? - if (foundPatternCross(stateCount)) - { - // Yes - bool confirmed = handlePossibleCenter(stateCount, i, j, pureBarcode); - if (confirmed) - { - // Start examining every other line. Checking each line turned out to be too - // expensive and didn't improve performance. - iSkip = 2; - if (hasSkipped) - { - done = haveMultiplyConfirmedCenters(); - } - else - { - int rowSkip = findRowSkip(); - if (rowSkip > stateCount[2]) - { - // Skip rows between row of lower confirmed center - // and top of presumed third confirmed center - // but back up a bit to get a full chance of detecting - // it, entire width of center of finder pattern - - // Skip by rowSkip, but back off by stateCount[2] (size of last center - // of pattern we saw) to be conservative, and also back off by iSkip which - // is about to be re-added - i += rowSkip - stateCount[2] - iSkip; - j = maxJ - 1; - } - } - } - else - { - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - continue; - } - // Clear state to start looking again - currentState = 0; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; - } - else - { - // No, shift counts back by two - stateCount[0] = stateCount[2]; - stateCount[1] = stateCount[3]; - stateCount[2] = stateCount[4]; - stateCount[3] = 1; - stateCount[4] = 0; - currentState = 3; - } - } - else - { - stateCount[++currentState]++; - } - } - else - { - // Counting white pixels - stateCount[currentState]++; - } - } - } - if (foundPatternCross(stateCount)) - { - bool confirmed = handlePossibleCenter(stateCount, i, maxJ, pureBarcode); - if (confirmed) - { - iSkip = stateCount[0]; - if (hasSkipped) - { - // Found a third one - done = haveMultiplyConfirmedCenters(); - } - } - } - } - - FinderPattern[] patternInfo = selectBestPatterns(); - if (patternInfo == null) - return null; - - ResultPoint.orderBestPatterns(patternInfo); - - return new FinderPatternInfo(patternInfo); - } - - /// Given a count of black/white/black/white/black pixels just seen and an end position, - /// figures the location of the center of this run. - /// - private static float? centerFromEnd(int[] stateCount, int end) - { - var result = (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0f; - if (Single.IsNaN(result)) - return null; - return result; - } - - /// count of black/white/black/white/black pixels just read - /// - /// true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios - /// used by finder patterns to be considered a match - /// - protected internal static bool foundPatternCross(int[] stateCount) - { - int totalModuleSize = 0; - for (int i = 0; i < 5; i++) - { - int count = stateCount[i]; - if (count == 0) - { - return false; - } - totalModuleSize += count; - } - if (totalModuleSize < 7) - { - return false; - } - int moduleSize = (totalModuleSize << INTEGER_MATH_SHIFT) / 7; - int maxVariance = moduleSize / 2; - // Allow less than 50% variance from 1-1-3-1-1 proportions - return Math.Abs(moduleSize - (stateCount[0] << INTEGER_MATH_SHIFT)) < maxVariance && - Math.Abs(moduleSize - (stateCount[1] << INTEGER_MATH_SHIFT)) < maxVariance && - Math.Abs(3 * moduleSize - (stateCount[2] << INTEGER_MATH_SHIFT)) < 3 * maxVariance && - Math.Abs(moduleSize - (stateCount[3] << INTEGER_MATH_SHIFT)) < maxVariance && - Math.Abs(moduleSize - (stateCount[4] << INTEGER_MATH_SHIFT)) < maxVariance; - } - - private int[] CrossCheckStateCount - { - get - { - crossCheckStateCount[0] = 0; - crossCheckStateCount[1] = 0; - crossCheckStateCount[2] = 0; - crossCheckStateCount[3] = 0; - crossCheckStateCount[4] = 0; - return crossCheckStateCount; - } - } - - /// - /// After a vertical and horizontal scan finds a potential finder pattern, this method - /// "cross-cross-cross-checks" by scanning down diagonally through the center of the possible - /// finder pattern to see if the same proportion is detected. - /// - /// row where a finder pattern was detected - /// center of the section that appears to cross a finder pattern - /// maximum reasonable number of modules that should be observed in any reading state, based on the results of the horizontal scan - /// The original state count total. - /// true if proportions are withing expected limits - private bool crossCheckDiagonal(int startI, int centerJ, int maxCount, int originalStateCountTotal) - { - int[] stateCount = CrossCheckStateCount; - - // Start counting up, left from center finding black center mass - int i = 0; - while (startI >= i && centerJ >= i && image[centerJ - i, startI - i]) - { - stateCount[2]++; - i++; - } - - if (startI < i || centerJ < i) - { - return false; - } - - // Continue up, left finding white space - while (startI >= i && centerJ >= i && !image[centerJ - i, startI - i] && - stateCount[1] <= maxCount) - { - stateCount[1]++; - i++; - } - - // If already too many modules in this state or ran off the edge: - if (startI < i || centerJ < i || stateCount[1] > maxCount) - { - return false; - } - - // Continue up, left finding black border - while (startI >= i && centerJ >= i && image[centerJ - i, startI - i] && - stateCount[0] <= maxCount) - { - stateCount[0]++; - i++; - } - if (stateCount[0] > maxCount) - { - return false; - } - - int maxI = image.Height; - int maxJ = image.Width; - - // Now also count down, right from center - i = 1; - while (startI + i < maxI && centerJ + i < maxJ && image[centerJ + i, startI + i]) - { - stateCount[2]++; - i++; - } - - // Ran off the edge? - if (startI + i >= maxI || centerJ + i >= maxJ) - { - return false; - } - - while (startI + i < maxI && centerJ + i < maxJ && !image[centerJ + i, startI + i] && - stateCount[3] < maxCount) - { - stateCount[3]++; - i++; - } - - if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) - { - return false; - } - - while (startI + i < maxI && centerJ + i < maxJ && image[centerJ + i, startI + i] && - stateCount[4] < maxCount) - { - stateCount[4]++; - i++; - } - - if (stateCount[4] >= maxCount) - { - return false; - } - - // If we found a finder-pattern-like section, but its size is more than 100% different than - // the original, assume it's a false positive - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; - return Math.Abs(stateCountTotal - originalStateCountTotal) < 2*originalStateCountTotal && - foundPatternCross(stateCount); - } - - /// - ///

After a horizontal scan finds a potential finder pattern, this method - /// "cross-checks" by scanning down vertically through the center of the possible - /// finder pattern to see if the same proportion is detected.

- ///
- /// row where a finder pattern was detected - /// center of the section that appears to cross a finder pattern - /// maximum reasonable number of modules that should be - /// observed in any reading state, based on the results of the horizontal scan - /// The original state count total. - /// - /// vertical center of finder pattern, or null if not found - /// - private float? crossCheckVertical(int startI, int centerJ, int maxCount, int originalStateCountTotal) - { - int maxI = image.Height; - int[] stateCount = CrossCheckStateCount; - - // Start counting up from center - int i = startI; - while (i >= 0 && image[centerJ, i]) - { - stateCount[2]++; - i--; - } - if (i < 0) - { - return null; - } - while (i >= 0 && !image[centerJ, i] && stateCount[1] <= maxCount) - { - stateCount[1]++; - i--; - } - // If already too many modules in this state or ran off the edge: - if (i < 0 || stateCount[1] > maxCount) - { - return null; - } - while (i >= 0 && image[centerJ, i] && stateCount[0] <= maxCount) - { - stateCount[0]++; - i--; - } - if (stateCount[0] > maxCount) - { - return null; - } - - // Now also count down from center - i = startI + 1; - while (i < maxI && image[centerJ, i]) - { - stateCount[2]++; - i++; - } - if (i == maxI) - { - return null; - } - while (i < maxI && !image[centerJ, i] && stateCount[3] < maxCount) - { - stateCount[3]++; - i++; - } - if (i == maxI || stateCount[3] >= maxCount) - { - return null; - } - while (i < maxI && image[centerJ, i] && stateCount[4] < maxCount) - { - stateCount[4]++; - i++; - } - if (stateCount[4] >= maxCount) - { - return null; - } - - // If we found a finder-pattern-like section, but its size is more than 40% different than - // the original, assume it's a false positive - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; - if (5 * Math.Abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) - { - return null; - } - - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : null; - } - - ///

Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical, - /// except it reads horizontally instead of vertically. This is used to cross-cross - /// check a vertical cross check and locate the real center of the alignment pattern.

- ///
- private float? crossCheckHorizontal(int startJ, int centerI, int maxCount, int originalStateCountTotal) - { - int maxJ = image.Width; - int[] stateCount = CrossCheckStateCount; - - int j = startJ; - while (j >= 0 && image[j, centerI]) - { - stateCount[2]++; - j--; - } - if (j < 0) - { - return null; - } - while (j >= 0 && !image[j, centerI] && stateCount[1] <= maxCount) - { - stateCount[1]++; - j--; - } - if (j < 0 || stateCount[1] > maxCount) - { - return null; - } - while (j >= 0 && image[j, centerI] && stateCount[0] <= maxCount) - { - stateCount[0]++; - j--; - } - if (stateCount[0] > maxCount) - { - return null; - } - - j = startJ + 1; - while (j < maxJ && image[j, centerI]) - { - stateCount[2]++; - j++; - } - if (j == maxJ) - { - return null; - } - while (j < maxJ && !image[j, centerI] && stateCount[3] < maxCount) - { - stateCount[3]++; - j++; - } - if (j == maxJ || stateCount[3] >= maxCount) - { - return null; - } - while (j < maxJ && image[j, centerI] && stateCount[4] < maxCount) - { - stateCount[4]++; - j++; - } - if (stateCount[4] >= maxCount) - { - return null; - } - - // If we found a finder-pattern-like section, but its size is significantly different than - // the original, assume it's a false positive - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; - if (5 * Math.Abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) - { - return null; - } - - return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : null; - } - - /// - ///

This is called when a horizontal scan finds a possible alignment pattern. It will - /// cross check with a vertical scan, and if successful, will, ah, cross-cross-check - /// with another horizontal scan. This is needed primarily to locate the real horizontal - /// center of the pattern in cases of extreme skew. - /// And then we cross-cross-cross check with another diagonal scan.

- /// If that succeeds the finder pattern location is added to a list that tracks - /// the number of times each location has been nearly-matched as a finder pattern. - /// Each additional find is more evidence that the location is in fact a finder - /// pattern center - ///
- /// reading state module counts from horizontal scan - /// row where finder pattern may be found - /// end of possible finder pattern in row - /// true if in "pure barcode" mode - /// - /// true if a finder pattern candidate was found this time - /// - protected bool handlePossibleCenter(int[] stateCount, int i, int j, bool pureBarcode) - { - int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + - stateCount[4]; - float? centerJ = centerFromEnd(stateCount, j); - if (centerJ == null) - return false; - float? centerI = crossCheckVertical(i, (int)centerJ.Value, stateCount[2], stateCountTotal); - if (centerI != null) - { - // Re-cross check - centerJ = crossCheckHorizontal((int)centerJ.Value, (int)centerI.Value, stateCount[2], stateCountTotal); - if (centerJ != null && - (!pureBarcode || crossCheckDiagonal((int) centerI, (int) centerJ, stateCount[2], stateCountTotal))) - { - float estimatedModuleSize = stateCountTotal / 7.0f; - bool found = false; - for (int index = 0; index < possibleCenters.Count; index++) - { - var center = possibleCenters[index]; - // Look for about the same center and module size: - if (center.aboutEquals(estimatedModuleSize, centerI.Value, centerJ.Value)) - { - possibleCenters.RemoveAt(index); - possibleCenters.Insert(index, center.combineEstimate(centerI.Value, centerJ.Value, estimatedModuleSize)); - - found = true; - break; - } - } - if (!found) - { - var point = new FinderPattern(centerJ.Value, centerI.Value, estimatedModuleSize); - - possibleCenters.Add(point); - if (resultPointCallback != null) - { - - resultPointCallback(point); - } - } - return true; - } - } - return false; - } - - /// number of rows we could safely skip during scanning, based on the first - /// two finder patterns that have been located. In some cases their position will - /// allow us to infer that the third pattern must lie below a certain point farther - /// down in the image. - /// - private int findRowSkip() - { - int max = possibleCenters.Count; - if (max <= 1) - { - return 0; - } - ResultPoint firstConfirmedCenter = null; - foreach (var center in possibleCenters) - { - if (center.Count >= CENTER_QUORUM) - { - if (firstConfirmedCenter == null) - { - firstConfirmedCenter = center; - } - else - { - // We have two confirmed centers - // How far down can we skip before resuming looking for the next - // pattern? In the worst case, only the difference between the - // difference in the x / y coordinates of the two centers. - // This is the case where you find top left last. - hasSkipped = true; - //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" - return (int)(Math.Abs(firstConfirmedCenter.X - center.X) - Math.Abs(firstConfirmedCenter.Y - center.Y)) / 2; - } - } - } - return 0; - } - - /// true iff we have found at least 3 finder patterns that have been detected - /// at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the - /// candidates is "pretty similar" - /// - private bool haveMultiplyConfirmedCenters() - { - int confirmedCount = 0; - float totalModuleSize = 0.0f; - int max = possibleCenters.Count; - foreach (var pattern in possibleCenters) - { - if (pattern.Count >= CENTER_QUORUM) - { - confirmedCount++; - totalModuleSize += pattern.EstimatedModuleSize; - } - } - if (confirmedCount < 3) - { - return false; - } - // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive" - // and that we need to keep looking. We detect this by asking if the estimated module sizes - // vary too much. We arbitrarily say that when the total deviation from average exceeds - // 5% of the total module size estimates, it's too much. - float average = totalModuleSize / max; - float totalDeviation = 0.0f; - for (int i = 0; i < max; i++) - { - var pattern = possibleCenters[i]; - totalDeviation += Math.Abs(pattern.EstimatedModuleSize - average); - } - return totalDeviation <= 0.05f * totalModuleSize; - } - - /// the 3 best {@link FinderPattern}s from our list of candidates. The "best" are - /// those that have been detected at least {@link #CENTER_QUORUM} times, and whose module - /// size differs from the average among those patterns the least - /// - private FinderPattern[] selectBestPatterns() - { - int startSize = possibleCenters.Count; - if (startSize < 3) - { - // Couldn't find enough finder patterns - return null; - } - - // Filter outlier possibilities whose module size is too different - if (startSize > 3) - { - // But we can only afford to do so if we have at least 4 possibilities to choose from - float totalModuleSize = 0.0f; - float square = 0.0f; - foreach (var center in possibleCenters) - { - float size = center.EstimatedModuleSize; - totalModuleSize += size; - square += size * size; - } - float average = totalModuleSize / startSize; - float stdDev = (float)Math.Sqrt(square / startSize - average * average); - - possibleCenters.Sort(new FurthestFromAverageComparator(average)); - - float limit = Math.Max(0.2f * average, stdDev); - - for (int i = 0; i < possibleCenters.Count && possibleCenters.Count > 3; i++) - { - FinderPattern pattern = possibleCenters[i]; - if (Math.Abs(pattern.EstimatedModuleSize - average) > limit) - { - possibleCenters.RemoveAt(i); - i--; - } - } - } - - if (possibleCenters.Count > 3) - { - // Throw away all but those first size candidate points we found. - - float totalModuleSize = 0.0f; - foreach (var possibleCenter in possibleCenters) - { - totalModuleSize += possibleCenter.EstimatedModuleSize; - } - - float average = totalModuleSize / possibleCenters.Count; - - possibleCenters.Sort(new CenterComparator(average)); - - //possibleCenters.subList(3, possibleCenters.Count).clear(); - possibleCenters = possibleCenters.GetRange(0, 3); - } - - return new[] - { - possibleCenters[0], - possibleCenters[1], - possibleCenters[2] - }; - } - - /// - /// Orders by furthest from average - /// - private sealed class FurthestFromAverageComparator : IComparer - { - private readonly float average; - - public FurthestFromAverageComparator(float f) - { - average = f; - } - - public int Compare(FinderPattern x, FinderPattern y) - { - float dA = Math.Abs(y.EstimatedModuleSize - average); - float dB = Math.Abs(x.EstimatedModuleSize - average); - return dA < dB ? -1 : dA == dB ? 0 : 1; - } - } - - ///

Orders by {@link FinderPattern#getCount()}, descending.

- private sealed class CenterComparator : IComparer - { - private readonly float average; - - public CenterComparator(float f) - { - average = f; - } - - public int Compare(FinderPattern x, FinderPattern y) - { - if (y.Count == x.Count) - { - float dA = Math.Abs(y.EstimatedModuleSize - average); - float dB = Math.Abs(x.EstimatedModuleSize - average); - return dA < dB ? 1 : dA == dB ? 0 : -1; - } - return y.Count - x.Count; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/detector/FinderPatternInfo.cs b/zxing.core/xx/qrcode/detector/FinderPatternInfo.cs deleted file mode 100644 index 4654d92..0000000 --- a/zxing.core/xx/qrcode/detector/FinderPatternInfo.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* -* Copyright 2007 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.QrCode.Internal -{ - /// - ///

Encapsulates information about finder patterns in an image, including the location of - /// the three finder patterns, and their estimated module size.

- ///
- /// Sean Owen - public sealed class FinderPatternInfo - { - private readonly FinderPattern bottomLeft; - private readonly FinderPattern topLeft; - private readonly FinderPattern topRight; - - /// - /// Initializes a new instance of the class. - /// - /// The pattern centers. - public FinderPatternInfo(FinderPattern[] patternCenters) - { - this.bottomLeft = patternCenters[0]; - this.topLeft = patternCenters[1]; - this.topRight = patternCenters[2]; - } - - /// - /// Gets the bottom left. - /// - public FinderPattern BottomLeft - { - get - { - return bottomLeft; - } - } - - /// - /// Gets the top left. - /// - public FinderPattern TopLeft - { - get - { - return topLeft; - } - } - - /// - /// Gets the top right. - /// - public FinderPattern TopRight - { - get - { - return topRight; - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/encoder/BlockPair.cs b/zxing.core/xx/qrcode/encoder/BlockPair.cs deleted file mode 100644 index c4c1691..0000000 --- a/zxing.core/xx/qrcode/encoder/BlockPair.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -namespace ZXing.QrCode.Internal -{ - internal sealed class BlockPair - { - private readonly byte[] dataBytes; - private readonly byte[] errorCorrectionBytes; - - public BlockPair(byte[] data, byte[] errorCorrection) - { - dataBytes = data; - errorCorrectionBytes = errorCorrection; - } - - public byte[] DataBytes - { - get { return dataBytes; } - } - - public byte[] ErrorCorrectionBytes - { - get { return errorCorrectionBytes; } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/encoder/ByteMatrix.cs b/zxing.core/xx/qrcode/encoder/ByteMatrix.cs deleted file mode 100644 index 1912073..0000000 --- a/zxing.core/xx/qrcode/encoder/ByteMatrix.cs +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2008 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -using System; -using System.Text; - -namespace ZXing.QrCode.Internal -{ - /// - /// JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned - /// 0, 1 and 2 I'm going to use less memory and go with bytes. - /// - /// dswitkin@google.com (Daniel Switkin) - public sealed class ByteMatrix - { - private readonly byte[][] bytes; - private readonly int width; - private readonly int height; - - /// - /// Initializes a new instance of the class. - /// - /// The width. - /// The height. - public ByteMatrix(int width, int height) - { - bytes = new byte[height][]; - for (var i = 0; i < height; i++) - bytes[i] = new byte[width]; - this.width = width; - this.height = height; - } - - /// - /// Gets the height. - /// - public int Height - { - get { return height; } - } - - /// - /// Gets the width. - /// - public int Width - { - get { return width; } - } - - /// - /// Gets or sets the with the specified x. - /// - public int this[int x, int y] - { - get { return bytes[y][x]; } - set { bytes[y][x] = (byte)value; } - } - - /// - /// an internal representation as bytes, in row-major order. array[y][x] represents point (x,y) - /// - public byte[][] Array - { - get { return bytes; } - } - - /// - /// Sets the specified x. - /// - /// The x. - /// The y. - /// The value. - public void set(int x, int y, byte value) - { - bytes[y][x] = value; - } - - /// - /// Sets the specified x. - /// - /// The x. - /// The y. - /// if set to true [value]. - public void set(int x, int y, bool value) - { - bytes[y][x] = (byte)(value ? 1 : 0); - } - - /// - /// Clears the specified value. - /// - /// The value. - public void clear(byte value) - { - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - bytes[y][x] = value; - } - } - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - override public String ToString() - { - var result = new StringBuilder(2 * width * height + 2); - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - switch (bytes[y][x]) - { - case 0: - result.Append(" 0"); - break; - case 1: - result.Append(" 1"); - break; - default: - result.Append(" "); - break; - } - } - result.Append('\n'); - } - return result.ToString(); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/encoder/Encoder.cs b/zxing.core/xx/qrcode/encoder/Encoder.cs deleted file mode 100644 index 2831a50..0000000 --- a/zxing.core/xx/qrcode/encoder/Encoder.cs +++ /dev/null @@ -1,758 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Collections.Generic; -using System.Text; - -using ZXing.Common; -using ZXing.Common.ReedSolomon; - -namespace ZXing.QrCode.Internal -{ - /// - /// - /// satorux@google.com (Satoru Takabayashi) - creator - /// dswitkin@google.com (Daniel Switkin) - ported from C++ - public static class Encoder - { - - // The original table is defined in the table 5 of JISX0510:2004 (p.19). - private static readonly int[] ALPHANUMERIC_TABLE = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f - }; - - internal static String DEFAULT_BYTE_MODE_ENCODING = "ISO-8859-1"; - - // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. - // Basically it applies four rules and summate all penalties. - private static int calculateMaskPenalty(ByteMatrix matrix) - { - return MaskUtil.applyMaskPenaltyRule1(matrix) - + MaskUtil.applyMaskPenaltyRule2(matrix) - + MaskUtil.applyMaskPenaltyRule3(matrix) - + MaskUtil.applyMaskPenaltyRule4(matrix); - } - - /// - /// Encode "bytes" with the error correction level "ecLevel". The encoding mode will be chosen - /// internally by chooseMode(). On success, store the result in "qrCode". - /// We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for - /// "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very - /// strong error correction for this purpose. - /// Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode() - /// with which clients can specify the encoding mode. For now, we don't need the functionality. - /// - /// text to encode - /// error correction level to use - /// representing the encoded QR code - public static QRCode encode(String content, ErrorCorrectionLevel ecLevel) - { - return encode(content, ecLevel, null); - } - - /// - /// Encodes the specified content. - /// - /// The content. - /// The ec level. - /// The hints. - /// - public static QRCode encode(String content, - ErrorCorrectionLevel ecLevel, - IDictionary hints) - { - // Determine what character encoding has been specified by the caller, if any -#if !SILVERLIGHT || WINDOWS_PHONE - String encoding = hints == null || !hints.ContainsKey(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET]; - if (encoding == null) - { - encoding = DEFAULT_BYTE_MODE_ENCODING; - } - bool generateECI = !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding); -#else - // Silverlight supports only UTF-8 and UTF-16 out-of-the-box - const string encoding = "UTF-8"; - // caller of the method can only control if the ECI segment should be written - // character set is fixed to UTF-8; but some scanners doesn't like the ECI segment - bool generateECI = (hints != null && hints.ContainsKey(EncodeHintType.CHARACTER_SET)); -#endif - - // Pick an encoding mode appropriate for the content. Note that this will not attempt to use - // multiple modes / segments even if that were more efficient. Twould be nice. - Mode mode = chooseMode(content, encoding); - - // This will store the header information, like mode and - // length, as well as "header" segments like an ECI segment. - BitArray headerBits = new BitArray(); - - // Append ECI segment if applicable - if (mode == Mode.BYTE && generateECI) - { - CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding); - if (eci != null) - { - var eciIsExplicitDisabled = (hints != null && hints.ContainsKey(EncodeHintType.DISABLE_ECI) ? (bool)hints[EncodeHintType.DISABLE_ECI] : false); - if (!eciIsExplicitDisabled) - { - appendECI(eci, headerBits); - } - } - } - - // (With ECI in place,) Write the mode marker - appendModeInfo(mode, headerBits); - - // Collect data within the main segment, separately, to count its size if needed. Don't add it to - // main payload yet. - BitArray dataBits = new BitArray(); - appendBytes(content, mode, dataBits, encoding); - - // Hard part: need to know version to know how many bits length takes. But need to know how many - // bits it takes to know version. First we take a guess at version by assuming version will be - // the minimum, 1: - - int provisionalBitsNeeded = headerBits.Size - + mode.getCharacterCountBits(Version.getVersionForNumber(1)) - + dataBits.Size; - Version provisionalVersion = chooseVersion(provisionalBitsNeeded, ecLevel); - - // Use that guess to calculate the right version. I am still not sure this works in 100% of cases. - int bitsNeeded = headerBits.Size - + mode.getCharacterCountBits(provisionalVersion) - + dataBits.Size; - Version version = chooseVersion(bitsNeeded, ecLevel); - - BitArray headerAndDataBits = new BitArray(); - headerAndDataBits.appendBitArray(headerBits); - // Find "length" of main segment and write it - int numLetters = mode == Mode.BYTE ? dataBits.SizeInBytes : content.Length; - appendLengthInfo(numLetters, version, mode, headerAndDataBits); - // Put data together into the overall payload - headerAndDataBits.appendBitArray(dataBits); - - Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); - int numDataBytes = version.TotalCodewords - ecBlocks.TotalECCodewords; - - // Terminate the bits properly. - terminateBits(numDataBytes, headerAndDataBits); - - // Interleave data bits with error correction code. - BitArray finalBits = interleaveWithECBytes(headerAndDataBits, - version.TotalCodewords, - numDataBytes, - ecBlocks.NumBlocks); - - QRCode qrCode = new QRCode - { - ECLevel = ecLevel, - Mode = mode, - Version = version - }; - - // Choose the mask pattern and set to "qrCode". - int dimension = version.DimensionForVersion; - ByteMatrix matrix = new ByteMatrix(dimension, dimension); - int maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix); - qrCode.MaskPattern = maskPattern; - - // Build the matrix and set it to "qrCode". - MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); - qrCode.Matrix = matrix; - - return qrCode; - } - - /// - /// Gets the alphanumeric code. - /// - /// The code. - /// the code point of the table used in alphanumeric mode or - /// -1 if there is no corresponding code in the table. - internal static int getAlphanumericCode(int code) - { - if (code < ALPHANUMERIC_TABLE.Length) - { - return ALPHANUMERIC_TABLE[code]; - } - return -1; - } - - /// - /// Chooses the mode. - /// - /// The content. - /// - public static Mode chooseMode(String content) - { - return chooseMode(content, null); - } - - /// - /// Choose the best mode by examining the content. Note that 'encoding' is used as a hint; - /// if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}. - /// - /// The content. - /// The encoding. - /// - private static Mode chooseMode(String content, String encoding) - { - if ("Shift_JIS".Equals(encoding)) - { - - // Choose Kanji mode if all input are double-byte characters - return isOnlyDoubleByteKanji(content) ? Mode.KANJI : Mode.BYTE; - } - bool hasNumeric = false; - bool hasAlphanumeric = false; - for (int i = 0; i < content.Length; ++i) - { - char c = content[i]; - if (c >= '0' && c <= '9') - { - hasNumeric = true; - } - else if (getAlphanumericCode(c) != -1) - { - hasAlphanumeric = true; - } - else - { - return Mode.BYTE; - } - } - if (hasAlphanumeric) - { - - return Mode.ALPHANUMERIC; - } - if (hasNumeric) - { - - return Mode.NUMERIC; - } - return Mode.BYTE; - } - - private static bool isOnlyDoubleByteKanji(String content) - { - byte[] bytes; - try - { - bytes = Encoding.GetEncoding("Shift_JIS").GetBytes(content); - } - catch (Exception ) - { - return false; - } - int length = bytes.Length; - if (length % 2 != 0) - { - return false; - } - for (int i = 0; i < length; i += 2) - { - - - int byte1 = bytes[i] & 0xFF; - if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) - { - - return false; - } - } - return true; - } - - private static int chooseMaskPattern(BitArray bits, - ErrorCorrectionLevel ecLevel, - Version version, - ByteMatrix matrix) - { - int minPenalty = Int32.MaxValue; // Lower penalty is better. - int bestMaskPattern = -1; - // We try all mask patterns to choose the best one. - for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) - { - - MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix); - int penalty = calculateMaskPenalty(matrix); - if (penalty < minPenalty) - { - - minPenalty = penalty; - bestMaskPattern = maskPattern; - } - } - return bestMaskPattern; - } - - private static Version chooseVersion(int numInputBits, ErrorCorrectionLevel ecLevel) - { - // In the following comments, we use numbers of Version 7-H. - for (int versionNum = 1; versionNum <= 40; versionNum++) - { - Version version = Version.getVersionForNumber(versionNum); - // numBytes = 196 - int numBytes = version.TotalCodewords; - // getNumECBytes = 130 - Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); - int numEcBytes = ecBlocks.TotalECCodewords; - // getNumDataBytes = 196 - 130 = 66 - int numDataBytes = numBytes - numEcBytes; - int totalInputBytes = (numInputBits + 7) / 8; - if (numDataBytes >= totalInputBytes) - { - return version; - } - } - throw new WriterException("Data too big"); - } - - /// - /// Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). - /// - /// The num data bytes. - /// The bits. - internal static void terminateBits(int numDataBytes, BitArray bits) - { - int capacity = numDataBytes << 3; - if (bits.Size > capacity) - { - throw new WriterException("data bits cannot fit in the QR Code" + bits.Size + " > " + - capacity); - } - for (int i = 0; i < 4 && bits.Size < capacity; ++i) - { - bits.appendBit(false); - } - // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details. - // If the last byte isn't 8-bit aligned, we'll add padding bits. - int numBitsInLastByte = bits.Size & 0x07; - if (numBitsInLastByte > 0) - { - for (int i = numBitsInLastByte; i < 8; i++) - { - bits.appendBit(false); - } - } - // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24). - int numPaddingBytes = numDataBytes - bits.SizeInBytes; - for (int i = 0; i < numPaddingBytes; ++i) - { - bits.appendBits((i & 0x01) == 0 ? 0xEC : 0x11, 8); - } - if (bits.Size != capacity) - { - throw new WriterException("Bits size does not equal capacity"); - } - } - - /// - /// Get number of data bytes and number of error correction bytes for block id "blockID". Store - /// the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of - /// JISX0510:2004 (p.30) - /// - /// The num total bytes. - /// The num data bytes. - /// The num RS blocks. - /// The block ID. - /// The num data bytes in block. - /// The num EC bytes in block. - internal static void getNumDataBytesAndNumECBytesForBlockID(int numTotalBytes, - int numDataBytes, - int numRSBlocks, - int blockID, - int[] numDataBytesInBlock, - int[] numECBytesInBlock) - { - if (blockID >= numRSBlocks) - { - throw new WriterException("Block ID too large"); - } - // numRsBlocksInGroup2 = 196 % 5 = 1 - int numRsBlocksInGroup2 = numTotalBytes % numRSBlocks; - // numRsBlocksInGroup1 = 5 - 1 = 4 - int numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2; - // numTotalBytesInGroup1 = 196 / 5 = 39 - int numTotalBytesInGroup1 = numTotalBytes / numRSBlocks; - // numTotalBytesInGroup2 = 39 + 1 = 40 - int numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1; - // numDataBytesInGroup1 = 66 / 5 = 13 - int numDataBytesInGroup1 = numDataBytes / numRSBlocks; - // numDataBytesInGroup2 = 13 + 1 = 14 - int numDataBytesInGroup2 = numDataBytesInGroup1 + 1; - // numEcBytesInGroup1 = 39 - 13 = 26 - int numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1; - // numEcBytesInGroup2 = 40 - 14 = 26 - int numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2; - // Sanity checks. - // 26 = 26 - if (numEcBytesInGroup1 != numEcBytesInGroup2) - { - - throw new WriterException("EC bytes mismatch"); - } - // 5 = 4 + 1. - if (numRSBlocks != numRsBlocksInGroup1 + numRsBlocksInGroup2) - { - - throw new WriterException("RS blocks mismatch"); - } - // 196 = (13 + 26) * 4 + (14 + 26) * 1 - if (numTotalBytes != - ((numDataBytesInGroup1 + numEcBytesInGroup1) * - numRsBlocksInGroup1) + - ((numDataBytesInGroup2 + numEcBytesInGroup2) * - numRsBlocksInGroup2)) - { - throw new WriterException("Total bytes mismatch"); - } - - if (blockID < numRsBlocksInGroup1) - { - - numDataBytesInBlock[0] = numDataBytesInGroup1; - numECBytesInBlock[0] = numEcBytesInGroup1; - } - else - { - - - numDataBytesInBlock[0] = numDataBytesInGroup2; - numECBytesInBlock[0] = numEcBytesInGroup2; - } - } - - /// - /// Interleave "bits" with corresponding error correction bytes. On success, store the result in - /// "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details. - /// - /// The bits. - /// The num total bytes. - /// The num data bytes. - /// The num RS blocks. - /// - internal static BitArray interleaveWithECBytes(BitArray bits, - int numTotalBytes, - int numDataBytes, - int numRSBlocks) - { - // "bits" must have "getNumDataBytes" bytes of data. - if (bits.SizeInBytes != numDataBytes) - { - - throw new WriterException("Number of bits and data bytes does not match"); - } - - // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll - // store the divided data bytes blocks and error correction bytes blocks into "blocks". - int dataBytesOffset = 0; - int maxNumDataBytes = 0; - int maxNumEcBytes = 0; - - // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number. - var blocks = new List(numRSBlocks); - - for (int i = 0; i < numRSBlocks; ++i) - { - - int[] numDataBytesInBlock = new int[1]; - int[] numEcBytesInBlock = new int[1]; - getNumDataBytesAndNumECBytesForBlockID( - numTotalBytes, numDataBytes, numRSBlocks, i, - numDataBytesInBlock, numEcBytesInBlock); - - int size = numDataBytesInBlock[0]; - byte[] dataBytes = new byte[size]; - bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size); - byte[] ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]); - blocks.Add(new BlockPair(dataBytes, ecBytes)); - - maxNumDataBytes = Math.Max(maxNumDataBytes, size); - maxNumEcBytes = Math.Max(maxNumEcBytes, ecBytes.Length); - dataBytesOffset += numDataBytesInBlock[0]; - } - if (numDataBytes != dataBytesOffset) - { - - throw new WriterException("Data bytes does not match offset"); - } - - BitArray result = new BitArray(); - - // First, place data blocks. - for (int i = 0; i < maxNumDataBytes; ++i) - { - foreach (BlockPair block in blocks) - { - byte[] dataBytes = block.DataBytes; - if (i < dataBytes.Length) - { - result.appendBits(dataBytes[i], 8); - } - } - } - // Then, place error correction blocks. - for (int i = 0; i < maxNumEcBytes; ++i) - { - foreach (BlockPair block in blocks) - { - byte[] ecBytes = block.ErrorCorrectionBytes; - if (i < ecBytes.Length) - { - result.appendBits(ecBytes[i], 8); - } - } - } - if (numTotalBytes != result.SizeInBytes) - { // Should be same. - throw new WriterException("Interleaving error: " + numTotalBytes + " and " + - result.SizeInBytes + " differ."); - } - - return result; - } - - internal static byte[] generateECBytes(byte[] dataBytes, int numEcBytesInBlock) - { - int numDataBytes = dataBytes.Length; - int[] toEncode = new int[numDataBytes + numEcBytesInBlock]; - for (int i = 0; i < numDataBytes; i++) - { - toEncode[i] = dataBytes[i] & 0xFF; - - } - new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock); - - byte[] ecBytes = new byte[numEcBytesInBlock]; - for (int i = 0; i < numEcBytesInBlock; i++) - { - ecBytes[i] = (byte)toEncode[numDataBytes + i]; - - } - return ecBytes; - } - - /// - /// Append mode info. On success, store the result in "bits". - /// - /// The mode. - /// The bits. - internal static void appendModeInfo(Mode mode, BitArray bits) - { - bits.appendBits(mode.Bits, 4); - } - - - /// - /// Append length info. On success, store the result in "bits". - /// - /// The num letters. - /// The version. - /// The mode. - /// The bits. - internal static void appendLengthInfo(int numLetters, Version version, Mode mode, BitArray bits) - { - int numBits = mode.getCharacterCountBits(version); - if (numLetters >= (1 << numBits)) - { - throw new WriterException(numLetters + " is bigger than " + ((1 << numBits) - 1)); - } - bits.appendBits(numLetters, numBits); - } - - /// - /// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". - /// - /// The content. - /// The mode. - /// The bits. - /// The encoding. - internal static void appendBytes(String content, - Mode mode, - BitArray bits, - String encoding) - { - if (mode.Equals(Mode.NUMERIC)) - appendNumericBytes(content, bits); - else - if (mode.Equals(Mode.ALPHANUMERIC)) - appendAlphanumericBytes(content, bits); - else - if (mode.Equals(Mode.BYTE)) - append8BitBytes(content, bits, encoding); - else - if (mode.Equals(Mode.KANJI)) - appendKanjiBytes(content, bits); - else - throw new WriterException("Invalid mode: " + mode); - } - - internal static void appendNumericBytes(String content, BitArray bits) - { - int length = content.Length; - - int i = 0; - while (i < length) - { - int num1 = content[i] - '0'; - if (i + 2 < length) - { - // Encode three numeric letters in ten bits. - int num2 = content[i + 1] - '0'; - int num3 = content[i + 2] - '0'; - bits.appendBits(num1 * 100 + num2 * 10 + num3, 10); - i += 3; - } - else if (i + 1 < length) - { - // Encode two numeric letters in seven bits. - int num2 = content[i + 1] - '0'; - bits.appendBits(num1 * 10 + num2, 7); - i += 2; - } - else - { - // Encode one numeric letter in four bits. - bits.appendBits(num1, 4); - i++; - } - } - } - - internal static void appendAlphanumericBytes(String content, BitArray bits) - { - int length = content.Length; - - int i = 0; - while (i < length) - { - int code1 = getAlphanumericCode(content[i]); - if (code1 == -1) - { - throw new WriterException(); - } - if (i + 1 < length) - { - int code2 = getAlphanumericCode(content[i + 1]); - if (code2 == -1) - { - throw new WriterException(); - } - // Encode two alphanumeric letters in 11 bits. - bits.appendBits(code1 * 45 + code2, 11); - i += 2; - } - else - { - // Encode one alphanumeric letter in six bits. - bits.appendBits(code1, 6); - i++; - } - } - } - - internal static void append8BitBytes(String content, BitArray bits, String encoding) - { - byte[] bytes; - try - { - bytes = Encoding.GetEncoding(encoding).GetBytes(content); - } -#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") - { - bytes = Encoding.GetEncoding(1252).GetBytes(content); - } - else - { - bytes = Encoding.GetEncoding("UTF-8").GetBytes(content); - } - } - catch (Exception uee) - { - throw new WriterException(uee.Message, uee); - } - } -#endif - catch (Exception uee) - { - throw new WriterException(uee.Message, uee); - } - foreach (byte b in bytes) - { - bits.appendBits(b, 8); - } - } - - internal static void appendKanjiBytes(String content, BitArray bits) - { - byte[] bytes; - try - { - bytes = Encoding.GetEncoding("Shift_JIS").GetBytes(content); - } - catch (Exception uee) - { - throw new WriterException(uee.Message, uee); - } - int length = bytes.Length; - for (int i = 0; i < length; i += 2) - { - int byte1 = bytes[i] & 0xFF; - int byte2 = bytes[i + 1] & 0xFF; - int code = (byte1 << 8) | byte2; - int subtracted = -1; - if (code >= 0x8140 && code <= 0x9ffc) - { - - subtracted = code - 0x8140; - } - else if (code >= 0xe040 && code <= 0xebbf) - { - subtracted = code - 0xc140; - } - if (subtracted == -1) - { - - throw new WriterException("Invalid byte sequence"); - } - int encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); - bits.appendBits(encoded, 13); - } - } - - private static void appendECI(CharacterSetECI eci, BitArray bits) - { - bits.appendBits(Mode.ECI.Bits, 4); - - // This is correct for values up to 127, which is all we need now. - bits.appendBits(eci.Value, 8); - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/encoder/MaskUtil.cs b/zxing.core/xx/qrcode/encoder/MaskUtil.cs deleted file mode 100644 index 1321293..0000000 --- a/zxing.core/xx/qrcode/encoder/MaskUtil.cs +++ /dev/null @@ -1,271 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; - -namespace ZXing.QrCode.Internal -{ - /// - /// - /// - /// Satoru Takabayashi - /// Daniel Switkin - /// Sean Owen - public static class MaskUtil - { - // Penalty weights from section 6.8.2.1 - private const int N1 = 3; - private const int N2 = 3; - private const int N3 = 40; - private const int N4 = 10; - - /// - /// Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and - /// give penalty to them. Example: 00000 or 11111. - /// - /// The matrix. - /// - public static int applyMaskPenaltyRule1(ByteMatrix matrix) - { - return applyMaskPenaltyRule1Internal(matrix, true) + applyMaskPenaltyRule1Internal(matrix, false); - } - - /// - /// Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give - /// penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a - /// penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block. - /// - /// The matrix. - /// - public static int applyMaskPenaltyRule2(ByteMatrix matrix) - { - int penalty = 0; - var array = matrix.Array; - int width = matrix.Width; - int height = matrix.Height; - for (int y = 0; y < height - 1; y++) - { - for (int x = 0; x < width - 1; x++) - { - int value = array[y][x]; - if (value == array[y][x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1]) - { - penalty++; - } - } - } - return N2 * penalty; - } - - /// - /// Apply mask penalty rule 3 and return the penalty. Find consecutive cells of 00001011101 or - /// 10111010000, and give penalty to them. If we find patterns like 000010111010000, we give - /// penalties twice (i.e. 40 * 2). - /// - /// The matrix. - /// - public static int applyMaskPenaltyRule3(ByteMatrix matrix) - { - int numPenalties = 0; - byte[][] array = matrix.Array; - int width = matrix.Width; - int height = matrix.Height; - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - byte[] arrayY = array[y]; // We can at least optimize this access - if (x + 6 < width && - arrayY[x] == 1 && - arrayY[x + 1] == 0 && - arrayY[x + 2] == 1 && - arrayY[x + 3] == 1 && - arrayY[x + 4] == 1 && - arrayY[x + 5] == 0 && - arrayY[x + 6] == 1 && - (isWhiteHorizontal(arrayY, x - 4, x) || isWhiteHorizontal(arrayY, x + 7, x + 11))) - { - numPenalties++; - } - if (y + 6 < height && - array[y][x] == 1 && - array[y + 1][x] == 0 && - array[y + 2][x] == 1 && - array[y + 3][x] == 1 && - array[y + 4][x] == 1 && - array[y + 5][x] == 0 && - array[y + 6][x] == 1 && - (isWhiteVertical(array, x, y - 4, y) || isWhiteVertical(array, x, y + 7, y + 11))) - { - numPenalties++; - } - } - } - return numPenalties * N3; - } - - private static bool isWhiteHorizontal(byte[] rowArray, int from, int to) - { - for (int i = from; i < to; i++) - { - if (i >= 0 && i < rowArray.Length && rowArray[i] == 1) - { - return false; - } - } - return true; - } - - private static bool isWhiteVertical(byte[][] array, int col, int from, int to) - { - for (int i = from; i < to; i++) - { - if (i >= 0 && i < array.Length && array[i][col] == 1) - { - return false; - } - } - return true; - } - - /// - /// Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give - /// penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance. - /// - /// The matrix. - /// - public static int applyMaskPenaltyRule4(ByteMatrix matrix) - { - int numDarkCells = 0; - var array = matrix.Array; - int width = matrix.Width; - int height = matrix.Height; - for (int y = 0; y < height; y++) - { - var arrayY = array[y]; - for (int x = 0; x < width; x++) - { - if (arrayY[x] == 1) - { - numDarkCells++; - } - } - } - var numTotalCells = matrix.Height * matrix.Width; - var darkRatio = (double)numDarkCells / numTotalCells; - var fivePercentVariances = (int)(Math.Abs(darkRatio - 0.5) * 20.0); // * 100.0 / 5.0 - return fivePercentVariances * N4; - } - - /// - /// Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask - /// pattern conditions. - /// - /// The mask pattern. - /// The x. - /// The y. - /// - public static bool getDataMaskBit(int maskPattern, int x, int y) - { - int intermediate, temp; - switch (maskPattern) - { - - case 0: - intermediate = (y + x) & 0x1; - break; - - case 1: - intermediate = y & 0x1; - break; - - case 2: - intermediate = x % 3; - break; - - case 3: - intermediate = (y + x) % 3; - break; - - case 4: - intermediate = (((int)((uint)y >> 1)) + (x / 3)) & 0x1; - break; - - case 5: - temp = y * x; - intermediate = (temp & 0x1) + (temp % 3); - break; - - case 6: - temp = y * x; - intermediate = (((temp & 0x1) + (temp % 3)) & 0x1); - break; - - case 7: - temp = y * x; - intermediate = (((temp % 3) + ((y + x) & 0x1)) & 0x1); - break; - - default: - throw new ArgumentException("Invalid mask pattern: " + maskPattern); - - } - return intermediate == 0; - } - - /// - /// Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both - /// vertical and horizontal orders respectively. - /// - /// The matrix. - /// if set to true [is horizontal]. - /// - private static int applyMaskPenaltyRule1Internal(ByteMatrix matrix, bool isHorizontal) - { - int penalty = 0; - int iLimit = isHorizontal ? matrix.Height : matrix.Width; - int jLimit = isHorizontal ? matrix.Width : matrix.Height; - var array = matrix.Array; - for (int i = 0; i < iLimit; i++) - { - int numSameBitCells = 0; - int prevBit = -1; - for (int j = 0; j < jLimit; j++) - { - int bit = isHorizontal ? array[i][j] : array[j][i]; - if (bit == prevBit) - { - numSameBitCells++; - } - else - { - if (numSameBitCells >= 5) - { - penalty += N1 + (numSameBitCells - 5); - } - numSameBitCells = 1; // Include the cell itself. - prevBit = bit; - } - } - if (numSameBitCells >= 5) - { - penalty += N1 + (numSameBitCells - 5); - } - } - return penalty; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/encoder/MatrixUtil.cs b/zxing.core/xx/qrcode/encoder/MatrixUtil.cs deleted file mode 100644 index 90dae10..0000000 --- a/zxing.core/xx/qrcode/encoder/MatrixUtil.cs +++ /dev/null @@ -1,604 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using ZXing.Common; - -namespace ZXing.QrCode.Internal -{ - /// - /// - /// - /// - /// satorux@google.com (Satoru Takabayashi) - creator - /// - public static class MatrixUtil - { - private static readonly int[][] POSITION_DETECTION_PATTERN = new int[][] - { - new int[] { 1, 1, 1, 1, 1, 1, 1 }, - new int[] { 1, 0, 0, 0, 0, 0, 1 }, - new int[] { 1, 0, 1, 1, 1, 0, 1 }, - new int[] { 1, 0, 1, 1, 1, 0, 1 }, - new int[] { 1, 0, 1, 1, 1, 0, 1 }, - new int[] { 1, 0, 0, 0, 0, 0, 1 }, - new int[] { 1, 1, 1, 1, 1, 1, 1 } - }; - - private static readonly int[][] POSITION_ADJUSTMENT_PATTERN = new int[][] - { - new int[] { 1, 1, 1, 1, 1 }, - new int[] { 1, 0, 0, 0, 1 }, - new int[] { 1, 0, 1, 0, 1 }, - new int[] { 1, 0, 0, 0, 1 }, - new int[] { 1, 1, 1, 1, 1 } - }; - - // From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu. - private static readonly int[][] POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = new int[][] - { - new int[] { -1, -1, -1, -1, -1, -1, -1 }, - new int[] { 6, 18, -1, -1, -1, -1, -1 }, - new int[] { 6, 22, -1, -1, -1, -1, -1 }, - new int[] { 6, 26, -1, -1, -1, -1, -1 }, - new int[] { 6, 30, -1, -1, -1, -1, -1 }, - new int[] { 6, 34, -1, -1, -1, -1, -1 }, - new int[] { 6, 22, 38, -1, -1, -1, -1 }, - new int[] { 6, 24, 42, -1, -1, -1, -1 }, - new int[] { 6, 26, 46, -1, -1, -1, -1 }, - new int[] { 6, 28, 50, -1, -1, -1, -1 }, - new int[] { 6, 30, 54, -1, -1, -1, -1 }, - new int[] { 6, 32, 58, -1, -1, -1, -1 }, - new int[] { 6, 34, 62, -1, -1, -1, -1 }, - new int[] { 6, 26, 46, 66, -1, -1, -1 }, - new int[] { 6, 26, 48, 70, -1, -1, -1 }, - new int[] { 6, 26, 50, 74, -1, -1, -1 }, - new int[] { 6, 30, 54, 78, -1, -1, -1 }, - new int[] { 6, 30, 56, 82, -1, -1, -1 }, - new int[] { 6, 30, 58, 86, -1, -1, -1 }, - new int[] { 6, 34, 62, 90, -1, -1, -1 }, - new int[] { 6, 28, 50, 72, 94, -1, -1 }, - new int[] { 6, 26, 50, 74, 98, -1, -1 }, - new int[] { 6, 30, 54, 78, 102, -1, -1 }, - new int[] { 6, 28, 54, 80, 106, -1, -1 }, - new int[] { 6, 32, 58, 84, 110, -1, -1 }, - new int[] { 6, 30, 58, 86, 114, -1, -1 }, - new int[] { 6, 34, 62, 90, 118, -1, -1 }, - new int[] { 6, 26, 50, 74, 98, 122, -1 }, - new int[] { 6, 30, 54, 78, 102, 126, -1 }, - new int[] { 6, 26, 52, 78, 104, 130, -1 }, - new int[] { 6, 30, 56, 82, 108, 134, -1 }, - new int[] { 6, 34, 60, 86, 112, 138, -1 }, - new int[] { 6, 30, 58, 86, 114, 142, -1 }, - new int[] { 6, 34, 62, 90, 118, 146, -1 }, - new int[] { 6, 30, 54, 78, 102, 126, 150 }, - new int[] { 6, 24, 50, 76, 102, 128, 154 }, - new int[] { 6, 28, 54, 80, 106, 132, 158 }, - new int[] { 6, 32, 58, 84, 110, 136, 162 }, - new int[] { 6, 26, 54, 82, 110, 138, 166 }, - new int[] { 6, 30, 58, 86, 114, 142, 170 } - }; - - // Type info cells at the left top corner. - private static readonly int[][] TYPE_INFO_COORDINATES = new int[][] - { - new int[] { 8, 0 }, - new int[] { 8, 1 }, - new int[] { 8, 2 }, - new int[] { 8, 3 }, - new int[] { 8, 4 }, - new int[] { 8, 5 }, - new int[] { 8, 7 }, - new int[] { 8, 8 }, - new int[] { 7, 8 }, - new int[] { 5, 8 }, - new int[] { 4, 8 }, - new int[] { 3, 8 }, - new int[] { 2, 8 }, - new int[] { 1, 8 }, - new int[] { 0, 8 } - }; - - // From Appendix D in JISX0510:2004 (p. 67) - private const int VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101 - - // From Appendix C in JISX0510:2004 (p.65). - private const int TYPE_INFO_POLY = 0x537; - private const int TYPE_INFO_MASK_PATTERN = 0x5412; - - /// - /// Set all cells to 2. 2 means that the cell is empty (not set yet). - /// - /// JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding - /// with the ByteMatrix initialized all to zero. - /// - /// The matrix. - public static void clearMatrix(ByteMatrix matrix) - { - matrix.clear(2); - } - - /// - /// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On - /// success, store the result in "matrix" and return true. - /// - /// The data bits. - /// The ec level. - /// The version. - /// The mask pattern. - /// The matrix. - public static void buildMatrix(BitArray dataBits, ErrorCorrectionLevel ecLevel, Version version, int maskPattern, ByteMatrix matrix) - { - clearMatrix(matrix); - embedBasicPatterns(version, matrix); - // Type information appear with any version. - embedTypeInfo(ecLevel, maskPattern, matrix); - // Version info appear if version >= 7. - maybeEmbedVersionInfo(version, matrix); - // Data should be embedded at end. - embedDataBits(dataBits, maskPattern, matrix); - } - - /// - /// Embed basic patterns. On success, modify the matrix and return true. - /// The basic patterns are: - /// - Position detection patterns - /// - Timing patterns - /// - Dark dot at the left bottom corner - /// - Position adjustment patterns, if need be - /// - /// The version. - /// The matrix. - public static void embedBasicPatterns(Version version, ByteMatrix matrix) - { - // Let's get started with embedding big squares at corners. - embedPositionDetectionPatternsAndSeparators(matrix); - // Then, embed the dark dot at the left bottom corner. - embedDarkDotAtLeftBottomCorner(matrix); - - // Position adjustment patterns appear if version >= 2. - maybeEmbedPositionAdjustmentPatterns(version, matrix); - // Timing patterns should be embedded after position adj. patterns. - embedTimingPatterns(matrix); - } - - /// - /// Embed type information. On success, modify the matrix. - /// - /// The ec level. - /// The mask pattern. - /// The matrix. - public static void embedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix) - { - BitArray typeInfoBits = new BitArray(); - makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits); - - for (int i = 0; i < typeInfoBits.Size; ++i) - { - // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in - // "typeInfoBits". - int bit = typeInfoBits[typeInfoBits.Size - 1 - i] ? 1 : 0; - - // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46). - int x1 = TYPE_INFO_COORDINATES[i][0]; - int y1 = TYPE_INFO_COORDINATES[i][1]; - matrix[x1, y1] = bit; - - if (i < 8) - { - // Right top corner. - int x2 = matrix.Width - i - 1; - int y2 = 8; - matrix[x2, y2] = bit; - } - else - { - // Left bottom corner. - int x2 = 8; - int y2 = matrix.Height - 7 + (i - 8); - matrix[x2, y2] = bit; - } - } - } - - /// - /// Embed version information if need be. On success, modify the matrix and return true. - /// See 8.10 of JISX0510:2004 (p.47) for how to embed version information. - /// - /// The version. - /// The matrix. - public static void maybeEmbedVersionInfo(Version version, ByteMatrix matrix) - { - if (version.VersionNumber < 7) - { - // Version info is necessary if version >= 7. - return; // Don't need version info. - } - BitArray versionInfoBits = new BitArray(); - makeVersionInfoBits(version, versionInfoBits); - - int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0. - for (int i = 0; i < 6; ++i) - { - for (int j = 0; j < 3; ++j) - { - // Place bits in LSB (least significant bit) to MSB order. - var bit = versionInfoBits[bitIndex] ? 1 : 0; - bitIndex--; - // Left bottom corner. - matrix[i, matrix.Height - 11 + j] = bit; - // Right bottom corner. - matrix[matrix.Height - 11 + j, i] = bit; - } - } - } - - /// - /// Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true. - /// For debugging purposes, it skips masking process if "getMaskPattern" is -1. - /// See 8.7 of JISX0510:2004 (p.38) for how to embed data bits. - /// - /// The data bits. - /// The mask pattern. - /// The matrix. - public static void embedDataBits(BitArray dataBits, int maskPattern, ByteMatrix matrix) - { - int bitIndex = 0; - int direction = -1; - // Start from the right bottom cell. - int x = matrix.Width - 1; - int y = matrix.Height - 1; - while (x > 0) - { - // Skip the vertical timing pattern. - if (x == 6) - { - x -= 1; - } - while (y >= 0 && y < matrix.Height) - { - for (int i = 0; i < 2; ++i) - { - int xx = x - i; - // Skip the cell if it's not empty. - if (!isEmpty(matrix[xx, y])) - { - continue; - } - int bit; - if (bitIndex < dataBits.Size) - { - bit = dataBits[bitIndex] ? 1 : 0; - ++bitIndex; - } - else - { - // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described - // in 8.4.9 of JISX0510:2004 (p. 24). - bit = 0; - } - - // Skip masking if mask_pattern is -1. - if (maskPattern != -1) - { - if (MaskUtil.getDataMaskBit(maskPattern, xx, y)) - { - bit ^= 0x1; - } - } - matrix[xx, y] = bit; - } - y += direction; - } - direction = -direction; // Reverse the direction. - y += direction; - x -= 2; // Move to the left. - } - // All bits should be consumed. - if (bitIndex != dataBits.Size) - { - throw new WriterException("Not all bits consumed: " + bitIndex + '/' + dataBits.Size); - } - } - - /// - /// Return the position of the most significant bit set (to one) in the "value". The most - /// significant bit is position 32. If there is no bit set, return 0. Examples: - /// - findMSBSet(0) => 0 - /// - findMSBSet(1) => 1 - /// - findMSBSet(255) => 8 - /// - /// The value_ renamed. - /// - public static int findMSBSet(int value_Renamed) - { - int numDigits = 0; - while (value_Renamed != 0) - { - value_Renamed = (int)((uint)value_Renamed >> 1); - ++numDigits; - } - return numDigits; - } - - /// - /// Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH - /// code is used for encoding type information and version information. - /// Example: Calculation of version information of 7. - /// f(x) is created from 7. - /// - 7 = 000111 in 6 bits - /// - f(x) = x^2 + x^2 + x^1 - /// g(x) is given by the standard (p. 67) - /// - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1 - /// Multiply f(x) by x^(18 - 6) - /// - f'(x) = f(x) * x^(18 - 6) - /// - f'(x) = x^14 + x^13 + x^12 - /// Calculate the remainder of f'(x) / g(x) - /// x^2 - /// __________________________________________________ - /// g(x) )x^14 + x^13 + x^12 - /// x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2 - /// -------------------------------------------------- - /// x^11 + x^10 + x^7 + x^4 + x^2 - /// - /// The remainder is x^11 + x^10 + x^7 + x^4 + x^2 - /// Encode it in binary: 110010010100 - /// The return value is 0xc94 (1100 1001 0100) - /// - /// Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit - /// operations. We don't care if cofficients are positive or negative. - /// - /// The value. - /// The poly. - /// - public static int calculateBCHCode(int value, int poly) - { - if (poly == 0) - throw new ArgumentException("0 polynominal", "poly"); - - // If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1 - // from 13 to make it 12. - int msbSetInPoly = findMSBSet(poly); - value <<= msbSetInPoly - 1; - // Do the division business using exclusive-or operations. - while (findMSBSet(value) >= msbSetInPoly) - { - value ^= poly << (findMSBSet(value) - msbSetInPoly); - } - // Now the "value" is the remainder (i.e. the BCH code) - return value; - } - - /// - /// Make bit vector of type information. On success, store the result in "bits" and return true. - /// Encode error correction level and mask pattern. See 8.9 of - /// JISX0510:2004 (p.45) for details. - /// - /// The ec level. - /// The mask pattern. - /// The bits. - public static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitArray bits) - { - if (!QRCode.isValidMaskPattern(maskPattern)) - { - throw new WriterException("Invalid mask pattern"); - } - int typeInfo = (ecLevel.Bits << 3) | maskPattern; - bits.appendBits(typeInfo, 5); - - int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY); - bits.appendBits(bchCode, 10); - - BitArray maskBits = new BitArray(); - maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15); - bits.xor(maskBits); - - if (bits.Size != 15) - { - // Just in case. - throw new WriterException("should not happen but we got: " + bits.Size); - } - } - - /// - /// Make bit vector of version information. On success, store the result in "bits" and return true. - /// See 8.10 of JISX0510:2004 (p.45) for details. - /// - /// The version. - /// The bits. - public static void makeVersionInfoBits(Version version, BitArray bits) - { - bits.appendBits(version.VersionNumber, 6); - int bchCode = calculateBCHCode(version.VersionNumber, VERSION_INFO_POLY); - bits.appendBits(bchCode, 12); - - if (bits.Size != 18) - { - // Just in case. - throw new WriterException("should not happen but we got: " + bits.Size); - } - } - - /// - /// Check if "value" is empty. - /// - /// The value. - /// - /// true if the specified value is empty; otherwise, false. - /// - private static bool isEmpty(int value) - { - return value == 2; - } - - private static void embedTimingPatterns(ByteMatrix matrix) - { - // -8 is for skipping position detection patterns (size 7), and two horizontal/vertical - // separation patterns (size 1). Thus, 8 = 7 + 1. - for (int i = 8; i < matrix.Width - 8; ++i) - { - int bit = (i + 1) % 2; - // Horizontal line. - if (isEmpty(matrix[i, 6])) - { - matrix[i, 6] = bit; - } - // Vertical line. - if (isEmpty(matrix[6, i])) - { - matrix[6, i] = bit; - } - } - } - - /// - /// Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46) - /// - /// The matrix. - private static void embedDarkDotAtLeftBottomCorner(ByteMatrix matrix) - { - if (matrix[8, matrix.Height - 8] == 0) - { - throw new WriterException(); - } - matrix[8, matrix.Height - 8] = 1; - } - - private static void embedHorizontalSeparationPattern(int xStart, int yStart, ByteMatrix matrix) - { - for (int x = 0; x < 8; ++x) - { - if (!isEmpty(matrix[xStart + x, yStart])) - { - throw new WriterException(); - } - matrix[xStart + x, yStart] = 0; - } - } - - private static void embedVerticalSeparationPattern(int xStart, int yStart, ByteMatrix matrix) - { - for (int y = 0; y < 7; ++y) - { - if (!isEmpty(matrix[xStart, yStart + y])) - { - throw new WriterException(); - } - matrix[xStart, yStart + y] = 0; - } - } - - /// - /// Note that we cannot unify the function with embedPositionDetectionPattern() despite they are - /// almost identical, since we cannot write a function that takes 2D arrays in different sizes in - /// C/C++. We should live with the fact. - /// - /// The x start. - /// The y start. - /// The matrix. - private static void embedPositionAdjustmentPattern(int xStart, int yStart, ByteMatrix matrix) - { - for (int y = 0; y < 5; ++y) - { - for (int x = 0; x < 5; ++x) - { - matrix[xStart + x, yStart + y] = POSITION_ADJUSTMENT_PATTERN[y][x]; - } - } - } - - private static void embedPositionDetectionPattern(int xStart, int yStart, ByteMatrix matrix) - { - for (int y = 0; y < 7; ++y) - { - for (int x = 0; x < 7; ++x) - { - matrix[xStart + x, yStart + y] = POSITION_DETECTION_PATTERN[y][x]; - } - } - } - - /// - /// Embed position detection patterns and surrounding vertical/horizontal separators. - /// - /// The matrix. - private static void embedPositionDetectionPatternsAndSeparators(ByteMatrix matrix) - { - // Embed three big squares at corners. - int pdpWidth = POSITION_DETECTION_PATTERN[0].Length; - // Left top corner. - embedPositionDetectionPattern(0, 0, matrix); - // Right top corner. - embedPositionDetectionPattern(matrix.Width - pdpWidth, 0, matrix); - // Left bottom corner. - embedPositionDetectionPattern(0, matrix.Width - pdpWidth, matrix); - - // Embed horizontal separation patterns around the squares. - const int hspWidth = 8; - // Left top corner. - embedHorizontalSeparationPattern(0, hspWidth - 1, matrix); - // Right top corner. - embedHorizontalSeparationPattern(matrix.Width - hspWidth, hspWidth - 1, matrix); - // Left bottom corner. - embedHorizontalSeparationPattern(0, matrix.Width - hspWidth, matrix); - - // Embed vertical separation patterns around the squares. - const int vspSize = 7; - // Left top corner. - embedVerticalSeparationPattern(vspSize, 0, matrix); - // Right top corner. - embedVerticalSeparationPattern(matrix.Height - vspSize - 1, 0, matrix); - // Left bottom corner. - embedVerticalSeparationPattern(vspSize, matrix.Height - vspSize, matrix); - } - - /// - /// Embed position adjustment patterns if need be. - /// - /// The version. - /// The matrix. - private static void maybeEmbedPositionAdjustmentPatterns(Version version, ByteMatrix matrix) - { - if (version.VersionNumber < 2) - { - // The patterns appear if version >= 2 - return; - } - int index = version.VersionNumber - 1; - int[] coordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index]; - int numCoordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index].Length; - for (int i = 0; i < numCoordinates; ++i) - { - for (int j = 0; j < numCoordinates; ++j) - { - int y = coordinates[i]; - int x = coordinates[j]; - if (x == -1 || y == -1) - { - continue; - } - // If the cell is unset, we embed the position adjustment pattern here. - if (isEmpty(matrix[x, y])) - { - // -2 is necessary since the x/y coordinates point to the center of the pattern, not the - // left top corner. - embedPositionAdjustmentPattern(x - 2, y - 2, matrix); - } - } - } - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/encoder/QRCode.cs b/zxing.core/xx/qrcode/encoder/QRCode.cs deleted file mode 100644 index 1d71ada..0000000 --- a/zxing.core/xx/qrcode/encoder/QRCode.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* -* Copyright 2008 ZXing authors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using System.Text; - -namespace ZXing.QrCode.Internal -{ - /// satorux@google.com (Satoru Takabayashi) - creator - /// dswitkin@google.com (Daniel Switkin) - ported from C++ - public sealed class QRCode - { - /// - /// - /// - public static int NUM_MASK_PATTERNS = 8; - - /// - /// Initializes a new instance of the class. - /// - public QRCode() - { - MaskPattern = -1; - } - - /// - /// Gets or sets the mode. - /// - /// - /// The mode. - /// - public Mode Mode { get; set; } - - /// - /// Gets or sets the EC level. - /// - /// - /// The EC level. - /// - public ErrorCorrectionLevel ECLevel { get; set; } - - /// - /// Gets or sets the version. - /// - /// - /// The version. - /// - public Version Version { get; set; } - - /// - /// Gets or sets the mask pattern. - /// - /// - /// The mask pattern. - /// - public int MaskPattern { get; set; } - - /// - /// Gets or sets the matrix. - /// - /// - /// The matrix. - /// - public ByteMatrix Matrix { get; set; } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - var result = new StringBuilder(200); - result.Append("<<\n"); - result.Append(" mode: "); - result.Append(Mode); - result.Append("\n ecLevel: "); - result.Append(ECLevel); - result.Append("\n version: "); - if (Version == null) - result.Append("null"); - else - result.Append(Version); - result.Append("\n maskPattern: "); - result.Append(MaskPattern); - if (Matrix == null) - { - result.Append("\n matrix: null\n"); - } - else - { - result.Append("\n matrix:\n"); - result.Append(Matrix.ToString()); - } - result.Append(">>\n"); - return result.ToString(); - } - - /// - /// Check if "mask_pattern" is valid. - /// - /// The mask pattern. - /// - /// true if [is valid mask pattern] [the specified mask pattern]; otherwise, false. - /// - public static bool isValidMaskPattern(int maskPattern) - { - return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS; - } - } -} \ No newline at end of file diff --git a/zxing.core/xx/qrcode/encoder/QrCodeEncodingOptions.cs b/zxing.core/xx/qrcode/encoder/QrCodeEncodingOptions.cs deleted file mode 100644 index 4f2d4ae..0000000 --- a/zxing.core/xx/qrcode/encoder/QrCodeEncodingOptions.cs +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 ZXing.Common; -using ZXing.QrCode.Internal; - -namespace ZXing.QrCode -{ - /// - /// The class holds the available options for the QrCodeWriter - /// - public class QrCodeEncodingOptions : EncodingOptions - { - /// - /// Specifies what degree of error correction to use, for example in QR Codes. - /// Type depends on the encoder. For example for QR codes it's type - /// {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}. - /// - public ErrorCorrectionLevel ErrorCorrection - { - get - { - if (Hints.ContainsKey(EncodeHintType.ERROR_CORRECTION)) - { - return (ErrorCorrectionLevel) Hints[EncodeHintType.ERROR_CORRECTION]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.ERROR_CORRECTION)) - Hints.Remove(EncodeHintType.ERROR_CORRECTION); - } - else - { - Hints[EncodeHintType.ERROR_CORRECTION] = value; - } - } - } - - /// - /// Specifies what character encoding to use where applicable (type {@link String}) - /// - public string CharacterSet - { - get - { - if (Hints.ContainsKey(EncodeHintType.CHARACTER_SET)) - { - return (string) Hints[EncodeHintType.CHARACTER_SET]; - } - return null; - } - set - { - if (value == null) - { - if (Hints.ContainsKey(EncodeHintType.CHARACTER_SET)) - Hints.Remove(EncodeHintType.CHARACTER_SET); - } - else - { - Hints[EncodeHintType.CHARACTER_SET] = value; - } - } - } - - /// - /// Explicitly disables ECI segment when generating QR Code - /// That is against the specification of QR Code but some - /// readers have problems if the charset is switched from - /// ISO-8859-1 (default) to UTF-8 with the necessary ECI segment. - /// If you set the property to true you can use UTF-8 encoding - /// and the ECI segment is omitted. - /// - public bool DisableECI - { - get - { - if (Hints.ContainsKey(EncodeHintType.DISABLE_ECI)) - { - return (bool)Hints[EncodeHintType.DISABLE_ECI]; - } - return false; - } - set - { - Hints[EncodeHintType.DISABLE_ECI] = value; - } - } - } -} diff --git a/zxing.core/xx/renderer/IBarcodeRenderer.cs b/zxing.core/xx/renderer/IBarcodeRenderer.cs deleted file mode 100644 index 15e10d0..0000000 --- a/zxing.core/xx/renderer/IBarcodeRenderer.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 ZXing.Common; - -namespace ZXing.Rendering -{ -#if !(WINDOWS_PHONE || WindowsCE) - /// - /// Interface for a class to convert a BitMatrix to an output image format - /// - public interface IBarcodeRenderer -#else - /// - /// Interface for a class to convert a BitMatrix to an output image format - /// - public interface IBarcodeRenderer -#endif - { - /// - /// Renders the specified matrix to its graphically representation - /// - /// The matrix. - /// The format. - /// The encoded content of the barcode which should be included in the image. - /// That can be the numbers below a 1D barcode or something other. - /// - TOutput Render(BitMatrix matrix, BarcodeFormat format, string content); - - /// - /// Renders the specified matrix to its graphically representation - /// - /// The matrix. - /// The format. - /// The encoded content of the barcode which should be included in the image. - /// That can be the numbers below a 1D barcode or something other. - /// The options. - /// - TOutput Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options); - } -} diff --git a/zxing.core/xx/renderer/PixelData.cs b/zxing.core/xx/renderer/PixelData.cs deleted file mode 100644 index d01ad8e..0000000 --- a/zxing.core/xx/renderer/PixelData.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.IO; - -namespace ZXing.Rendering -{ - public sealed class PixelData - { - internal PixelData(int width, int height, byte[] pixels) - { - Height = height; - Width = width; - Pixels = pixels; - } - - public byte[] Pixels { get; private set; } - public int Width { get; private set; } - public int Height { get; private set; } - -#if (NET45 || NET40 || NET35 || NET20 || WindowsCE) && !UNITY - public System.Drawing.Bitmap ToBitmap() - { -#if WindowsCE - var bmp = new System.Drawing.Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb); - var bmpData = bmp.LockBits( - new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), - System.Drawing.Imaging.ImageLockMode.WriteOnly, - System.Drawing.Imaging.PixelFormat.Format32bppRgb); -#else - var bmp = new System.Drawing.Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - bmp.SetResolution(96, 96); - var bmpData = bmp.LockBits( - new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), - System.Drawing.Imaging.ImageLockMode.WriteOnly, - System.Drawing.Imaging.PixelFormat.Format32bppArgb); -#endif - try - { - //Copy the data from the byte array into BitmapData.Scan0 - System.Runtime.InteropServices.Marshal.Copy(Pixels, 0, bmpData.Scan0, Pixels.Length); - } - finally - { - //Unlock the pixels - bmp.UnlockBits(bmpData); - } - - return bmp; - } -#endif - -#if UNITY - // Unity3D -#endif - -#if NETFX_CORE - public Windows.UI.Xaml.Media.Imaging.WriteableBitmap ToBitmap() - { - var bmp = new Windows.UI.Xaml.Media.Imaging.WriteableBitmap(Width, Height); - using (var stream = System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.AsStream(bmp.PixelBuffer)) - { - stream.Write(Pixels, 0, Pixels.Length); - } - bmp.Invalidate(); - return bmp; - } -#endif - -#if SILVERLIGHT - public System.Windows.Media.Imaging.WriteableBitmap ToBitmap() - { - var bmp = new System.Windows.Media.Imaging.WriteableBitmap(Width, Height); - bmp.SetSource(new MemoryStream(Pixels)); - bmp.Invalidate(); - return bmp; - } -#endif - -#if MONOANDROID - public Android.Graphics.Bitmap ToBitmap() - { - var pixels = Pixels; - var colors = new int[Width*Height]; - for (var index = 0; index < Width*Height; index++) - { - colors[index] = - pixels[index*4] << 24 | - pixels[index*4 + 1] << 16 | - pixels[index*4 + 2] << 8 | - pixels[index*4 + 3]; - } - return Android.Graphics.Bitmap.CreateBitmap(colors, Width, Height, Android.Graphics.Bitmap.Config.Argb8888); - } -#endif - -#if MONOTOUCH -#if __UNIFIED__ -using UIKit; -#else -using MonoTouch.UIKit; -#endif -#endif - - } -} diff --git a/zxing.core/xx/renderer/RawRenderer.cs b/zxing.core/xx/renderer/RawRenderer.cs deleted file mode 100644 index 8bef55a..0000000 --- a/zxing.core/xx/renderer/RawRenderer.cs +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2014 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 ZXing.Common; - -namespace ZXing.Rendering -{ - /// - /// Renders a to a byte array with ARGB 32bit data - /// - [Obsolete("please use PixelDataRenderer instead")] - public class RawRenderer : IBarcodeRenderer - { - public struct Color - { - public static Color Black = new Color(0); - public static Color White = new Color(0x00FFFFFF); - - public byte A; - public byte R; - public byte G; - public byte B; - - public Color(int color) - { - A = (byte)((color & 0xFF000000) >> 24); - R = (byte)((color & 0x00FF0000) >> 16); - G = (byte)((color & 0x0000FF00) >> 8); - B = (byte)((color & 0x000000FF)); - } - } - - /// - /// Gets or sets the foreground color. - /// - /// - /// The foreground color. - /// - public Color Foreground { get; set; } - /// - /// Gets or sets the background color. - /// - /// - /// The background color. - /// - public Color Background { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public RawRenderer() - { - Foreground = Color.Black; - Background = Color.White; - } - - /// - /// Renders the specified matrix. - /// - /// The matrix. - /// The format. - /// The content. - /// - public byte[] Render(BitMatrix matrix, BarcodeFormat format, string content) - { - return Render(matrix, format, content, null); - } - - /// - /// Renders the specified matrix. - /// - /// The matrix. - /// The format. - /// The content. - /// The options. - /// - virtual public byte[] Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options) - { - int width = matrix.Width; - int height = matrix.Height; - bool outputContent = (options == null || !options.PureBarcode) && - !String.IsNullOrEmpty(content) && (format == BarcodeFormat.CODE_39 || - format == BarcodeFormat.CODE_128 || - format == BarcodeFormat.EAN_13 || - format == BarcodeFormat.EAN_8 || - format == BarcodeFormat.CODABAR || - format == BarcodeFormat.ITF || - format == BarcodeFormat.UPC_A || - format == BarcodeFormat.MSI || - format == BarcodeFormat.PLESSEY); - int emptyArea = outputContent ? 16 : 0; - int pixelsize = 1; - - if (options != null) - { - if (options.Width > width) - { - width = options.Width; - } - if (options.Height > height) - { - height = options.Height; - } - // calculating the scaling factor - pixelsize = width / matrix.Width; - if (pixelsize > height / matrix.Height) - { - pixelsize = height / matrix.Height; - } - } - - var pixels = new byte[width*height*4]; - var index = 0; - - for (int y = 0; y < matrix.Height - emptyArea; y++) - { - for (var pixelsizeHeight = 0; pixelsizeHeight < pixelsize; pixelsizeHeight++) - { - for (var x = 0; x < matrix.Width; x++) - { - var color = matrix[x, y] ? Foreground : Background; - for (var pixelsizeWidth = 0; pixelsizeWidth < pixelsize; pixelsizeWidth++) - { - pixels[index++] = color.A; - pixels[index++] = color.R; - pixels[index++] = color.G; - pixels[index++] = color.B; - } - } - for (var x = pixelsize * matrix.Width; x < width; x++) - { - pixels[index++] = Background.A; - pixels[index++] = Background.R; - pixels[index++] = Background.G; - pixels[index++] = Background.B; - } - } - } - for (int y = matrix.Height * pixelsize - emptyArea; y < height; y++) - { - for (var x = 0; x < width; x++) - { - pixels[index++] = Background.A; - pixels[index++] = Background.R; - pixels[index++] = Background.G; - pixels[index++] = Background.B; - } - } - - return pixels; - } - } -} diff --git a/zxing.core/zxing.core/zxing.core.csproj b/zxing.core/zxing.core/zxing.core.csproj index ec2fc35..ce0fad0 100644 --- a/zxing.core/zxing.core/zxing.core.csproj +++ b/zxing.core/zxing.core/zxing.core.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1;net462;net472 + netcoreapp3.1 true