mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-04-25 02:46:38 +08:00
项目结构调整
This commit is contained in:
9
Others/zxing.core/WPFDemo/App.xaml
Normal file
9
Others/zxing.core/WPFDemo/App.xaml
Normal file
@@ -0,0 +1,9 @@
|
||||
<Application x:Class="WPFDemo.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:WPFDemo"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
17
Others/zxing.core/WPFDemo/App.xaml.cs
Normal file
17
Others/zxing.core/WPFDemo/App.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace WPFDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
||||
10
Others/zxing.core/WPFDemo/AssemblyInfo.cs
Normal file
10
Others/zxing.core/WPFDemo/AssemblyInfo.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
64
Others/zxing.core/WPFDemo/MainWindow.xaml
Normal file
64
Others/zxing.core/WPFDemo/MainWindow.xaml
Normal file
@@ -0,0 +1,64 @@
|
||||
<Window x:Class="WPFDemo.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="MainWindow" Height="380" Width="531" ResizeMode="CanResize">
|
||||
<Grid>
|
||||
|
||||
<TabControl Height="Auto" Margin="0,1,0,0" Name="tabControl1" Width="Auto">
|
||||
<TabItem Header="Decode" Name="tabItemDecode">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="100" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBox Grid.Column="0" Grid.Row="0" Height="23" HorizontalAlignment="Stretch" Margin="12,46,30,0" Name="txtBarcodeImageFile" VerticalAlignment="Top" Width="Auto" IsReadOnly="True" TextChanged="txtBarcodeImageFile_TextChanged" />
|
||||
<Button Grid.Column="0" Grid.Row="0" Content="..." Height="23" HorizontalAlignment="Right" Margin="465,46,0,0" Name="btnSelectFile" VerticalAlignment="Top" Width="26" Click="btnSelectFile_Click" />
|
||||
<Label Grid.Column="0" Grid.Row="0" Content="Barcode Image File" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" Width="124" />
|
||||
<Button Grid.Column="0" Grid.Row="0" Content="Decode" Height="23" HorizontalAlignment="Right" Margin="416,75,0,0" Name="btnDecode" VerticalAlignment="Top" Width="75" Click="btnDecode_Click" />
|
||||
<Grid Grid.Column="0" Grid.Row="1" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="350" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Image Grid.Column="0" Grid.Row="0" Height="Auto" HorizontalAlignment="Left" Margin="0,0,0,0" Name="imageBarcode" Stretch="None" VerticalAlignment="Top" Width="Auto" />
|
||||
<TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="0,64,0,0" Name="txtBarcodeType" VerticalAlignment="Top" Width="265" IsReadOnly="True" />
|
||||
<Label Grid.Column="1" Grid.Row="0" Content="Barcode Type" Height="28" HorizontalAlignment="Left" Margin="0,30,0,0" Name="label2" VerticalAlignment="Top" Width="95" />
|
||||
<Label Grid.Column="1" Grid.Row="0" Content="Content" Height="28" HorizontalAlignment="Left" Margin="0,93,0,0" Name="label3" VerticalAlignment="Top" Width="95" />
|
||||
<TextBox Grid.Column="1" Grid.Row="0" Height="97" HorizontalAlignment="Left" Margin="0,127,0,0" Name="txtBarcodeContent" VerticalAlignment="Top" Width="265" IsReadOnly="True" />
|
||||
<Label Grid.Column="1" Grid.Row="0" Height="28" HorizontalAlignment="Left" Margin="0,0,0,0" Name="labDuration" VerticalAlignment="Top" Width="184" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Header="Encode" Name="tabItemEncode">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="290" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Border BorderBrush="#202020" BorderThickness="1" CornerRadius="4">
|
||||
<Image Grid.Column="0" Grid.Row="0" Height="Auto" HorizontalAlignment="Stretch" Name="imageBarcodeEncoder" Stretch="Uniform" VerticalAlignment="Stretch" Width="Auto" />
|
||||
</Border>
|
||||
<Border BorderBrush="#202020" BorderThickness="1" CornerRadius="4">
|
||||
<Path Grid.Column="0" Grid.Row="0" Name="imageBarcodeEncoderGeometry" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="Black" Width="Auto" Height="Auto" />
|
||||
</Border>
|
||||
<Button Grid.Column="1" Grid.Row="0" Content="Encode" Height="23" HorizontalAlignment="Right" Margin="190,269,10,0" Name="btnEncode" VerticalAlignment="Top" Width="75" Click="btnEncode_Click" />
|
||||
<Label Grid.Column="1" Grid.Row="0" Content="Barcode Type" Height="28" HorizontalAlignment="Right" Margin="0,6,180,0" Name="label4" VerticalAlignment="Top" Width="95" />
|
||||
<Label Grid.Column="1" Grid.Row="0" Content="Content" Height="28" HorizontalAlignment="Right" Margin="0,132,180,0" Name="label5" VerticalAlignment="Top" Width="95" />
|
||||
<TextBox Grid.Column="1" Grid.Row="0" Height="97" HorizontalAlignment="Right" Margin="0,166,10,0" Name="txtBarcodeContentEncode" VerticalAlignment="Top" Width="265" />
|
||||
<ComboBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Right" Margin="0,40,10,0" Name="cmbEncoderType" VerticalAlignment="Top" Width="265" />
|
||||
<ComboBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Right" Margin="0,103,10,0" Name="cmbRendererType" VerticalAlignment="Top" Width="265" />
|
||||
<Label Grid.Column="1" Grid.Row="0" Content="Renderer Type" Height="28" HorizontalAlignment="Right" Margin="0,69,180,0" Name="label6" VerticalAlignment="Top" Width="95" />
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</Window>
|
||||
134
Others/zxing.core/WPFDemo/MainWindow.xaml.cs
Normal file
134
Others/zxing.core/WPFDemo/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
using Microsoft.Win32;
|
||||
using ZXing;
|
||||
|
||||
using BarcodeReader = ZXing.Presentation.BarcodeReader;
|
||||
using BarcodeWriter = ZXing.Presentation.BarcodeWriter;
|
||||
using BarcodeWriterGeometry = ZXing.Presentation.BarcodeWriterGeometry;
|
||||
|
||||
namespace WPFDemo
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly BarcodeReader reader = new BarcodeReader();
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
foreach (var format in MultiFormatWriter.SupportedWriters)
|
||||
cmbEncoderType.Items.Add(format);
|
||||
cmbEncoderType.SelectedItem = BarcodeFormat.QR_CODE;
|
||||
|
||||
cmbRendererType.Items.Add("WriteableBitmap");
|
||||
cmbRendererType.Items.Add("XAML Geometry");
|
||||
cmbRendererType.SelectedItem = "WriteableBitmap";
|
||||
}
|
||||
|
||||
private void btnSelectFile_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new OpenFileDialog
|
||||
{
|
||||
Filter = "All documents (*.*)|*.*",
|
||||
FileName = txtBarcodeImageFile.Text
|
||||
};
|
||||
if (dlg.ShowDialog(this).GetValueOrDefault(false))
|
||||
{
|
||||
txtBarcodeImageFile.Text = dlg.FileName;
|
||||
}
|
||||
}
|
||||
|
||||
private void btnDecode_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var start = DateTime.Now;
|
||||
var result = reader.Decode((BitmapSource)imageBarcode.Source);
|
||||
labDuration.Content = (DateTime.Now - start).Milliseconds + " ms";
|
||||
if (result != null)
|
||||
{
|
||||
txtBarcodeType.Text = result.BarcodeFormat.ToString();
|
||||
txtBarcodeContent.Text = result.Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
txtBarcodeType.Text = "";
|
||||
txtBarcodeContent.Text = "No barcode found.";
|
||||
}
|
||||
}
|
||||
|
||||
private void txtBarcodeImageFile_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (File.Exists(txtBarcodeImageFile.Text))
|
||||
{
|
||||
imageBarcode.Source = new BitmapImage(new Uri(txtBarcodeImageFile.Text));
|
||||
}
|
||||
}
|
||||
|
||||
private void btnEncode_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
imageBarcodeEncoder.Visibility = Visibility.Hidden;
|
||||
imageBarcodeEncoderGeometry.Visibility = Visibility.Hidden;
|
||||
|
||||
switch (cmbRendererType.SelectedItem.ToString())
|
||||
{
|
||||
case "WriteableBitmap":
|
||||
{
|
||||
var writer = new BarcodeWriter
|
||||
{
|
||||
Format = (BarcodeFormat)cmbEncoderType.SelectedItem,
|
||||
Options = new ZXing.Common.EncodingOptions
|
||||
{
|
||||
Height = (int)((FrameworkElement)imageBarcodeEncoder.Parent).ActualHeight,
|
||||
Width = (int)((FrameworkElement)imageBarcodeEncoder.Parent).ActualWidth,
|
||||
Margin = 0
|
||||
}
|
||||
};
|
||||
var image = writer.Write(txtBarcodeContentEncode.Text);
|
||||
imageBarcodeEncoder.Source = image;
|
||||
imageBarcodeEncoder.Visibility = Visibility.Visible;
|
||||
}
|
||||
break;
|
||||
case "XAML Geometry":
|
||||
{
|
||||
var writer = new BarcodeWriterGeometry
|
||||
{
|
||||
Format = (BarcodeFormat)cmbEncoderType.SelectedItem,
|
||||
Options = new ZXing.Common.EncodingOptions
|
||||
{
|
||||
Height = (int)((FrameworkElement)imageBarcodeEncoder.Parent).ActualHeight,
|
||||
Width = (int)((FrameworkElement)imageBarcodeEncoder.Parent).ActualWidth,
|
||||
Margin = 0
|
||||
}
|
||||
};
|
||||
var image = writer.Write(txtBarcodeContentEncode.Text);
|
||||
imageBarcodeEncoderGeometry.Data = image;
|
||||
imageBarcodeEncoderGeometry.Visibility = Visibility.Visible;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Others/zxing.core/WPFDemo/WPFDemo.csproj
Normal file
13
Others/zxing.core/WPFDemo/WPFDemo.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\zxing.core\zxing.core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
31
Others/zxing.core/zxing.core.sln
Normal file
31
Others/zxing.core/zxing.core.sln
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29905.134
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPFDemo", "WPFDemo\WPFDemo.csproj", "{85681BF4-62DA-42A6-A921-BED5865C1A8C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zxing.core", "zxing.core\zxing.core.csproj", "{B1E14F51-DEE6-4D33-B3EF-B1B553F9CDC2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{85681BF4-62DA-42A6-A921-BED5865C1A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85681BF4-62DA-42A6-A921-BED5865C1A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85681BF4-62DA-42A6-A921-BED5865C1A8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85681BF4-62DA-42A6-A921-BED5865C1A8C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B1E14F51-DEE6-4D33-B3EF-B1B553F9CDC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B1E14F51-DEE6-4D33-B3EF-B1B553F9CDC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B1E14F51-DEE6-4D33-B3EF-B1B553F9CDC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B1E14F51-DEE6-4D33-B3EF-B1B553F9CDC2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B855CA10-D6A4-4ED5-9E49-628767623C7E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
95
Others/zxing.core/zxing.core/BarcodeFormat.cs
Normal file
95
Others/zxing.core/zxing.core/BarcodeFormat.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerates barcode formats known to this package.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
[System.Flags]
|
||||
public enum BarcodeFormat
|
||||
{
|
||||
/// <summary>Aztec 2D barcode format.</summary>
|
||||
AZTEC = 1,
|
||||
|
||||
/// <summary>CODABAR 1D format.</summary>
|
||||
CODABAR = 2,
|
||||
|
||||
/// <summary>Code 39 1D format.</summary>
|
||||
CODE_39 = 4,
|
||||
|
||||
/// <summary>Code 93 1D format.</summary>
|
||||
CODE_93 = 8,
|
||||
|
||||
/// <summary>Code 128 1D format.</summary>
|
||||
CODE_128 = 16,
|
||||
|
||||
/// <summary>Data Matrix 2D barcode format.</summary>
|
||||
DATA_MATRIX = 32,
|
||||
|
||||
/// <summary>EAN-8 1D format.</summary>
|
||||
EAN_8 = 64,
|
||||
|
||||
/// <summary>EAN-13 1D format.</summary>
|
||||
EAN_13 = 128,
|
||||
|
||||
/// <summary>ITF (Interleaved Two of Five) 1D format.</summary>
|
||||
ITF = 256,
|
||||
|
||||
/// <summary>MaxiCode 2D barcode format.</summary>
|
||||
MAXICODE = 512,
|
||||
|
||||
/// <summary>PDF417 format.</summary>
|
||||
PDF_417 = 1024,
|
||||
|
||||
/// <summary>QR Code 2D barcode format.</summary>
|
||||
QR_CODE = 2048,
|
||||
|
||||
/// <summary>RSS 14</summary>
|
||||
RSS_14 = 4096,
|
||||
|
||||
/// <summary>RSS EXPANDED</summary>
|
||||
RSS_EXPANDED = 8192,
|
||||
|
||||
/// <summary>UPC-A 1D format.</summary>
|
||||
UPC_A = 16384,
|
||||
|
||||
/// <summary>UPC-E 1D format.</summary>
|
||||
UPC_E = 32768,
|
||||
|
||||
/// <summary>UPC/EAN extension format. Not a stand-alone format.</summary>
|
||||
UPC_EAN_EXTENSION = 65536,
|
||||
|
||||
/// <summary>MSI</summary>
|
||||
MSI = 131072,
|
||||
|
||||
/// <summary>Plessey</summary>
|
||||
PLESSEY = 262144,
|
||||
|
||||
/// <summary>Intelligent Mail barcode</summary>
|
||||
IMB = 524288,
|
||||
|
||||
/// <summary>Pharmacode format.</summary>
|
||||
PHARMA_CODE = 1048576,
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
/// </summary>
|
||||
All_1D = UPC_A | UPC_E | EAN_13 | EAN_8 | CODABAR | CODE_39 | CODE_93 | CODE_128 | ITF | RSS_14 | RSS_EXPANDED
|
||||
}
|
||||
}
|
||||
74
Others/zxing.core/zxing.core/BarcodeReader.Bitmap.cs
Normal file
74
Others/zxing.core/zxing.core/BarcodeReader.Bitmap.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// A smart class to decode the barcode inside a bitmap object
|
||||
/// </summary>
|
||||
public class BarcodeReader : BarcodeReader<Bitmap>, IBarcodeReader
|
||||
{
|
||||
private static readonly Func<Bitmap, LuminanceSource> defaultCreateLuminanceSource =
|
||||
(bitmap) => new BitmapLuminanceSource(bitmap);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class.
|
||||
/// </summary>
|
||||
public BarcodeReader()
|
||||
: this(null, defaultCreateLuminanceSource, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode.
|
||||
/// If null then MultiFormatReader is used</param>
|
||||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap.
|
||||
/// If null, an exception is thrown when Decode is called</param>
|
||||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source.
|
||||
/// If null then HybridBinarizer is used</param>
|
||||
public BarcodeReader(Reader reader,
|
||||
Func<Bitmap, LuminanceSource> createLuminanceSource,
|
||||
Func<LuminanceSource, Binarizer> createBinarizer
|
||||
)
|
||||
: base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode.
|
||||
/// If null then MultiFormatReader is used</param>
|
||||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap.
|
||||
/// If null, an exception is thrown when Decode is called</param>
|
||||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source.
|
||||
/// If null then HybridBinarizer is used</param>
|
||||
/// <param name="createRGBLuminanceSource">Sets the function to create a luminance source object for a rgb raw byte array.</param>
|
||||
public BarcodeReader(Reader reader,
|
||||
Func<Bitmap, LuminanceSource> createLuminanceSource,
|
||||
Func<LuminanceSource, Binarizer> createBinarizer,
|
||||
Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource
|
||||
)
|
||||
: base(reader, createLuminanceSource ?? defaultCreateLuminanceSource, createBinarizer, createRGBLuminanceSource)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
144
Others/zxing.core/zxing.core/BarcodeReaderCustom.cs
Normal file
144
Others/zxing.core/zxing.core/BarcodeReaderCustom.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2012 ZXing.Net authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// A smart class to decode the barcode inside a bitmap object
|
||||
/// </summary>
|
||||
public class BarcodeReader<T> : BarcodeReaderGeneric, IBarcodeReader<T>
|
||||
{
|
||||
private readonly Func<T, LuminanceSource> createLuminanceSource;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class.
|
||||
/// </summary>
|
||||
public BarcodeReader(Func<T, LuminanceSource> createLuminanceSource)
|
||||
: this(null, createLuminanceSource, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode.
|
||||
/// If null then MultiFormatReader is used</param>
|
||||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap.
|
||||
/// If null, an exception is thrown when Decode is called</param>
|
||||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source.
|
||||
/// If null then HybridBinarizer is used</param>
|
||||
public BarcodeReader(Reader reader,
|
||||
Func<T, LuminanceSource> createLuminanceSource,
|
||||
Func<LuminanceSource, Binarizer> createBinarizer
|
||||
)
|
||||
: this(reader, createLuminanceSource, createBinarizer, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode.
|
||||
/// If null then MultiFormatReader is used</param>
|
||||
/// <param name="createLuminanceSource">Sets the function to create a luminance source object for a bitmap.
|
||||
/// If null, an exception is thrown when Decode is called</param>
|
||||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source.
|
||||
/// If null then HybridBinarizer is used</param>
|
||||
/// <param name="createRGBLuminanceSource">Sets the function to create a luminance source object for a rgb raw byte array.</param>
|
||||
public BarcodeReader(Reader reader,
|
||||
Func<T, LuminanceSource> createLuminanceSource,
|
||||
Func<LuminanceSource, Binarizer> createBinarizer,
|
||||
Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource
|
||||
)
|
||||
: base(reader, createBinarizer, createRGBLuminanceSource)
|
||||
{
|
||||
this.createLuminanceSource = createLuminanceSource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for additional image formats for one BarcodeReader class
|
||||
/// </summary>
|
||||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode.
|
||||
/// If null then MultiFormatReader is used</param>
|
||||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source.
|
||||
/// If null then HybridBinarizer is used</param>
|
||||
/// <param name="createRGBLuminanceSource">Sets the function to create a luminance source object for a rgb raw byte array.</param>
|
||||
protected BarcodeReader(Reader reader,
|
||||
Func<LuminanceSource, Binarizer> createBinarizer,
|
||||
Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource
|
||||
)
|
||||
: base(reader, createBinarizer, createRGBLuminanceSource)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional: Gets or sets the function to create a luminance source object for a bitmap.
|
||||
/// If null a platform specific default LuminanceSource is used
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The function to create a luminance source object.
|
||||
/// </value>
|
||||
protected Func<T, LuminanceSource> CreateLuminanceSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return createLuminanceSource;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap.
|
||||
/// </summary>
|
||||
/// <param name="barcodeBitmap">The barcode bitmap.</param>
|
||||
/// <returns>the result data or null</returns>
|
||||
public Result Decode(T barcodeBitmap)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap.
|
||||
/// </summary>
|
||||
/// <param name="barcodeBitmap">The barcode bitmap.</param>
|
||||
/// <returns>the result data or null</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
442
Others/zxing.core/zxing.core/BarcodeReaderGeneric.cs
Normal file
442
Others/zxing.core/zxing.core/BarcodeReaderGeneric.cs
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// A smart class to decode the barcode inside a bitmap object
|
||||
/// </summary>
|
||||
public class BarcodeReaderGeneric : IBarcodeReaderGeneric
|
||||
{
|
||||
private static readonly Func<LuminanceSource, Binarizer> defaultCreateBinarizer =
|
||||
(luminanceSource) => new HybridBinarizer(luminanceSource);
|
||||
|
||||
/// <summary>
|
||||
/// represents the default function which is called to get a <see cref="RGBLuminanceSource"/> instance from a raw byte array
|
||||
/// </summary>
|
||||
protected static readonly Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> defaultCreateRGBLuminanceSource =
|
||||
(rawBytes, width, height, format) => new RGBLuminanceSource(rawBytes, width, height, format);
|
||||
|
||||
private Reader reader;
|
||||
private readonly Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource;
|
||||
|
||||
private readonly Func<LuminanceSource, Binarizer> createBinarizer;
|
||||
private bool usePreviousState;
|
||||
private DecodingOptions options;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The options.
|
||||
/// </value>
|
||||
public DecodingOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
options = new DecodingOptions();
|
||||
options.ValueChanged += (o, args) => usePreviousState = false;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
options = value;
|
||||
options.ValueChanged += (o, args) => usePreviousState = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
options = null;
|
||||
}
|
||||
usePreviousState = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reader which should be used to find and decode the barcode.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The reader.
|
||||
/// </value>
|
||||
protected Reader Reader
|
||||
{
|
||||
get
|
||||
{
|
||||
return reader ?? (reader = new MultiFormatReader());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a method which is called if an important point is found
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The result point callback.
|
||||
/// </value>
|
||||
public event Action<ResultPoint> ResultPointFound
|
||||
{
|
||||
add
|
||||
{
|
||||
if (!Options.Hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
|
||||
{
|
||||
var callback = new ResultPointCallback(OnResultPointFound);
|
||||
Options.Hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK] = callback;
|
||||
}
|
||||
explicitResultPointFound += value;
|
||||
usePreviousState = false;
|
||||
}
|
||||
remove
|
||||
{
|
||||
explicitResultPointFound -= value;
|
||||
if (explicitResultPointFound == null)
|
||||
Options.Hints.Remove(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
|
||||
usePreviousState = false;
|
||||
}
|
||||
}
|
||||
|
||||
private event Action<ResultPoint> explicitResultPointFound;
|
||||
|
||||
/// <summary>
|
||||
/// event is executed if a result was found via decode
|
||||
/// </summary>
|
||||
public event Action<Result> ResultFound;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the image should be automatically rotated.
|
||||
/// Rotation is supported for 90, 180 and 270 degrees
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if image should be rotated; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool AutoRotate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the image should be automatically inverted
|
||||
/// if no result is found in the original image.
|
||||
/// ATTENTION: Please be carefully because it slows down the decoding process if it is used
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if image should be inverted; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool TryInverted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: Gets or sets the function to create a binarizer object for a luminance source.
|
||||
/// If null then HybridBinarizer is used
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The function to create a binarizer object.
|
||||
/// </value>
|
||||
protected Func<LuminanceSource, Binarizer> CreateBinarizer
|
||||
{
|
||||
get
|
||||
{
|
||||
return createBinarizer ?? defaultCreateBinarizer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReaderGeneric"/> class.
|
||||
/// </summary>
|
||||
public BarcodeReaderGeneric()
|
||||
: this(new MultiFormatReader(), defaultCreateBinarizer, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeReaderGeneric"/> class.
|
||||
/// </summary>
|
||||
/// <param name="reader">Sets the reader which should be used to find and decode the barcode.
|
||||
/// If null then MultiFormatReader is used</param>
|
||||
/// <param name="createBinarizer">Sets the function to create a binarizer object for a luminance source.
|
||||
/// If null then HybridBinarizer is used</param>
|
||||
/// <param name="createRGBLuminanceSource">Sets the function to create a luminance source object for a rgb array.
|
||||
/// If null the RGBLuminanceSource is used. The handler is only called when Decode with a byte[] array is called.</param>
|
||||
public BarcodeReaderGeneric(Reader reader,
|
||||
Func<LuminanceSource, Binarizer> createBinarizer,
|
||||
Func<byte[], int, int, RGBLuminanceSource.BitmapFormat, LuminanceSource> createRGBLuminanceSource
|
||||
)
|
||||
{
|
||||
this.reader = reader ?? new MultiFormatReader();
|
||||
this.createBinarizer = createBinarizer ?? defaultCreateBinarizer;
|
||||
this.createRGBLuminanceSource = createRGBLuminanceSource ?? defaultCreateRGBLuminanceSource;
|
||||
usePreviousState = false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tries to decode a barcode within an image which is given by a luminance source.
|
||||
/// That method gives a chance to prepare a luminance source completely before calling
|
||||
/// the time consuming decoding method. On the other hand there is a chance to create
|
||||
/// a luminance source which is independent from external resources (like Bitmap objects)
|
||||
/// and the decoding call can be made in a background thread.
|
||||
/// </summary>
|
||||
/// <param name="luminanceSource">The luminance source.</param>
|
||||
/// <returns></returns>
|
||||
public virtual 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;
|
||||
|
||||
luminanceSource = luminanceSource.rotateCounterClockwise();
|
||||
binarizer = CreateBinarizer(luminanceSource);
|
||||
binaryBitmap = new BinaryBitmap(binarizer);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="luminanceSource">The luminance source.</param>
|
||||
/// <returns></returns>
|
||||
public virtual 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// raises the ResultFound event
|
||||
/// </summary>
|
||||
/// <param name="results"></param>
|
||||
protected void OnResultsFound(IEnumerable<Result> results)
|
||||
{
|
||||
if (ResultFound != null)
|
||||
{
|
||||
foreach (var result in results)
|
||||
{
|
||||
ResultFound(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// raises the ResultFound event
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
protected void OnResultFound(Result result)
|
||||
{
|
||||
if (ResultFound != null)
|
||||
{
|
||||
ResultFound(result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calls the explicitResultPointFound action
|
||||
/// </summary>
|
||||
/// <param name="resultPoint"></param>
|
||||
protected void OnResultPointFound(ResultPoint resultPoint)
|
||||
{
|
||||
if (explicitResultPointFound != null)
|
||||
{
|
||||
explicitResultPointFound(resultPoint);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap.
|
||||
/// </summary>
|
||||
/// <param name="rawRGB">The image as byte[] array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <returns>
|
||||
/// the result data or null
|
||||
/// </returns>
|
||||
public Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format)
|
||||
{
|
||||
if (rawRGB == null)
|
||||
throw new ArgumentNullException("rawRGB");
|
||||
|
||||
var luminanceSource = createRGBLuminanceSource(rawRGB, width, height, format);
|
||||
|
||||
return Decode(luminanceSource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap.
|
||||
/// </summary>
|
||||
/// <param name="rawRGB">The image as byte[] array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <returns>
|
||||
/// the result data or null
|
||||
/// </returns>
|
||||
public Result[] 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Others/zxing.core/zxing.core/BarcodeWriter.Bitmap.cs
Normal file
34
Others/zxing.core/zxing.core/BarcodeWriter.Bitmap.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.Rendering;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// A smart class to encode some content to a barcode image
|
||||
/// </summary>
|
||||
public class BarcodeWriter : BarcodeWriter<System.Drawing.Bitmap>, IBarcodeWriter
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeWriter"/> class.
|
||||
/// </summary>
|
||||
public BarcodeWriter()
|
||||
{
|
||||
Renderer = new BitmapRenderer();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Others/zxing.core/zxing.core/BarcodeWriter.PixelData.cs
Normal file
34
Others/zxing.core/zxing.core/BarcodeWriter.PixelData.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.Rendering;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// A smart class to encode some content to raw pixel data
|
||||
/// </summary>
|
||||
public class BarcodeWriterPixelData : BarcodeWriter<PixelData>, IBarcodeWriterPixelData
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeWriterPixelData"/> class.
|
||||
/// </summary>
|
||||
public BarcodeWriterPixelData()
|
||||
{
|
||||
Renderer = new PixelDataRenderer();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Others/zxing.core/zxing.core/BarcodeWriter.SvgImage.cs
Normal file
34
Others/zxing.core/zxing.core/BarcodeWriter.SvgImage.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.Rendering;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// A smart class to encode some content to a svg barcode image
|
||||
/// </summary>
|
||||
public class BarcodeWriterSvg : BarcodeWriter<SvgRenderer.SvgImage>, IBarcodeWriterSvg
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BarcodeWriterSvg"/> class.
|
||||
/// </summary>
|
||||
public BarcodeWriterSvg()
|
||||
{
|
||||
Renderer = new SvgRenderer();
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Others/zxing.core/zxing.core/BarcodeWriterCustom.cs
Normal file
71
Others/zxing.core/zxing.core/BarcodeWriterCustom.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for specific barcode writers with specific formats of barcode images.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOutput">The type of the output.</typeparam>
|
||||
public class BarcodeWriter<TOutput> : BarcodeWriterGeneric, IBarcodeWriter<TOutput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the renderer which should be used to render the encoded BitMatrix.
|
||||
/// </summary>
|
||||
public IBarcodeRenderer<TOutput> Renderer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents.</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="matrix">The matrix.</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
84
Others/zxing.core/zxing.core/BarcodeWriterGeneric.cs
Normal file
84
Others/zxing.core/zxing.core/BarcodeWriterGeneric.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for specific barcode writers with specific formats of barcode images.
|
||||
/// </summary>
|
||||
public class BarcodeWriterGeneric : IBarcodeWriterGeneric
|
||||
{
|
||||
private EncodingOptions options;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the barcode format.
|
||||
/// The value is only suitable if the MultiFormatWriter is used.
|
||||
/// </summary>
|
||||
public BarcodeFormat Format { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options container for the encoding and renderer process.
|
||||
/// </summary>
|
||||
public EncodingOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return (options ?? (options = new EncodingOptions { Height = 100, Width = 100 }));
|
||||
}
|
||||
set
|
||||
{
|
||||
options = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the writer which encodes the content to a BitMatrix.
|
||||
/// If no value is set the MultiFormatWriter is used.
|
||||
/// </summary>
|
||||
public Writer Encoder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BarcodeWriterGeneric()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="encoder"></param>
|
||||
public BarcodeWriterGeneric(Writer encoder)
|
||||
{
|
||||
Encoder = encoder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the specified contents and returns a BitMatrix array.
|
||||
/// That array has to be rendered manually or with a IBarcodeRenderer.
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents.</param>
|
||||
/// <returns></returns>
|
||||
public BitMatrix Encode(string contents)
|
||||
{
|
||||
var encoder = Encoder ?? new MultiFormatWriter();
|
||||
var currentOptions = Options;
|
||||
return encoder.encode(contents, Format, currentOptions.Width, currentOptions.Height, currentOptions.Hints);
|
||||
}
|
||||
}
|
||||
}
|
||||
228
Others/zxing.core/zxing.core/BaseLuminanceSource.cs
Normal file
228
Others/zxing.core/zxing.core/BaseLuminanceSource.cs
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright 2012 ZXing.Net authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// The base class for luminance sources which supports
|
||||
/// cropping and rotating based upon the luminance values.
|
||||
/// </summary>
|
||||
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
|
||||
/// <summary>
|
||||
/// weight of the red channel for calculating a gray scale image
|
||||
/// </summary>
|
||||
protected const int RChannelWeight = 19562;
|
||||
/// <summary>
|
||||
/// weight of the green channel for calculating a gray scale image
|
||||
/// </summary>
|
||||
protected const int GChannelWeight = 38550;
|
||||
/// <summary>
|
||||
/// weight of the blue channel for calculating a gray scale image
|
||||
/// </summary>
|
||||
protected const int BChannelWeight = 7424;
|
||||
/// <summary>
|
||||
/// numbers of bits which for right shifting
|
||||
/// </summary>
|
||||
protected const int ChannelWeight = 16;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected byte[] luminances;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BaseLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
luminances = new byte[width * height];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="luminanceArray">The luminance array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BaseLuminanceSource(byte[] luminanceArray, int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
luminances = new byte[width * height];
|
||||
Buffer.BlockCopy(luminanceArray, 0, luminances, 0, width * height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, 0 <= y < Height.</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// Always use the returned object, and ignore the .length of the array.</param>
|
||||
/// <returns>
|
||||
/// An array containing the luminance data.
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// gets the luminance matrix
|
||||
/// </summary>
|
||||
public override byte[] Matrix
|
||||
{
|
||||
get { return luminances; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
/// Only callable if {@link #isRotateSupported()} is true.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A rotated version of this object.
|
||||
/// </returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: not implemented yet
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A rotated version of this object.
|
||||
/// </returns>
|
||||
public override LuminanceSource rotateCounterClockwise45()
|
||||
{
|
||||
// TODO: implement a good 45 degrees rotation without lost of information
|
||||
return base.rotateCounterClockwise45();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports counter-clockwise rotation.</returns>
|
||||
public override bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
/// original data rather than a copy. Only callable if CropSupported is true.
|
||||
/// </summary>
|
||||
/// <param name="left">The left coordinate, 0 <= left < Width.</param>
|
||||
/// <param name="top">The top coordinate, 0 <= top <= Height.</param>
|
||||
/// <param name="width">The width of the rectangle to crop.</param>
|
||||
/// <param name="height">The height of the rectangle to crop.</param>
|
||||
/// <returns>
|
||||
/// A cropped version of this object.
|
||||
/// </returns>
|
||||
public 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports cropping.</returns>
|
||||
public override bool CropSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns>Whether this subclass supports invertion.</returns>
|
||||
public override bool InversionSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inverts the luminance values (newValue = 255 - oldValue)
|
||||
/// </summary>
|
||||
public override LuminanceSource invert()
|
||||
{
|
||||
return new InvertedLuminanceSource(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected abstract LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height);
|
||||
}
|
||||
}
|
||||
104
Others/zxing.core/zxing.core/Binarizer.cs
Normal file
104
Others/zxing.core/zxing.core/Binarizer.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary> This class hierarchy provides a set of methods to convert luminance data to 1 bit data.
|
||||
/// It allows the algorithm to vary polymorphically, for example allowing a very expensive
|
||||
/// thresholding technique for servers and a fast one for mobile. It also permits the implementation
|
||||
/// to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.
|
||||
///
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
/// </summary>
|
||||
public abstract class Binarizer
|
||||
{
|
||||
private readonly LuminanceSource source;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Binarizer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">The source.</param>
|
||||
protected internal Binarizer(LuminanceSource source)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentException("Source must be non-null.");
|
||||
}
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the luminance source object.
|
||||
/// </summary>
|
||||
virtual public LuminanceSource LuminanceSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
|
||||
/// cached data. Callers should assume this method is expensive and call it as seldom as possible.
|
||||
/// This method is intended for decoding 1D barcodes and may choose to apply sharpening.
|
||||
/// For callers which only examine one row of pixels at a time, the same BitArray should be reused
|
||||
/// and passed in with each call for performance. However it is legal to keep more than one row
|
||||
/// at a time if needed.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, which must be in [0, bitmap height)</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// If used, the Binarizer will call BitArray.clear(). Always use the returned object.
|
||||
/// </param>
|
||||
/// <returns> The array of bits for this row (true means black).</returns>
|
||||
public abstract BitArray getBlackRow(int y, BitArray row);
|
||||
|
||||
/// <summary> Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive
|
||||
/// and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
|
||||
/// may not apply sharpening. Therefore, a row from this matrix may not be identical to one
|
||||
/// fetched using getBlackRow(), so don't mix and match between them.
|
||||
/// </summary>
|
||||
/// <returns> The 2D array of bits for the image (true means black).</returns>
|
||||
public abstract BitMatrix BlackMatrix { get; }
|
||||
|
||||
/// <summary> Creates a new object with the same type as this Binarizer implementation, but with pristine
|
||||
/// state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache
|
||||
/// of 1 bit data. See Effective Java for why we can't use Java's clone() method.
|
||||
/// </summary>
|
||||
/// <param name="source">The LuminanceSource this Binarizer will operate on.</param>
|
||||
/// <returns> A new concrete Binarizer implementation object.</returns>
|
||||
public abstract Binarizer createBinarizer(LuminanceSource source);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the width of the luminance source object.
|
||||
/// </summary>
|
||||
public int Width
|
||||
{
|
||||
get { return source.Width; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the height of the luminance source object.
|
||||
/// </summary>
|
||||
public int Height
|
||||
{
|
||||
get { return source.Height; }
|
||||
}
|
||||
}
|
||||
}
|
||||
182
Others/zxing.core/zxing.core/BinaryBitmap.cs
Normal file
182
Others/zxing.core/zxing.core/BinaryBitmap.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects
|
||||
/// accept a BinaryBitmap and attempt to decode it.
|
||||
/// </summary>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
public sealed class BinaryBitmap
|
||||
{
|
||||
private readonly Binarizer binarizer;
|
||||
private BitMatrix matrix;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="binarizer"></param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// The width of the bitmap.
|
||||
/// </returns>
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return binarizer.Width;
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// The height of the bitmap.
|
||||
/// </returns>
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return binarizer.Height;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
|
||||
/// cached data. Callers should assume this method is expensive and call it as seldom as possible.
|
||||
/// This method is intended for decoding 1D barcodes and may choose to apply sharpening.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, which must be in [0, bitmap height).</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// If used, the Binarizer will call BitArray.clear(). Always use the returned object.
|
||||
/// </param>
|
||||
/// <returns> The array of bits for this row (true means black).</returns>
|
||||
public BitArray getBlackRow(int y, BitArray row)
|
||||
{
|
||||
return binarizer.getBlackRow(y, row);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive
|
||||
/// and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
|
||||
/// may not apply sharpening. Therefore, a row from this matrix may not be identical to one
|
||||
/// fetched using getBlackRow(), so don't mix and match between them.
|
||||
/// </summary>
|
||||
/// <returns> The 2D array of bits for the image (true means black).</returns>
|
||||
public BitMatrix BlackMatrix
|
||||
{
|
||||
get
|
||||
{
|
||||
// The matrix is created on demand the first time it is requested, then cached. There are two
|
||||
// reasons for this:
|
||||
// 1. This work will never be done if the caller only installs 1D Reader objects, or if a
|
||||
// 1D Reader finds a barcode before the 2D Readers run.
|
||||
// 2. This work will only be done once even if the caller installs multiple 2D Readers.
|
||||
return matrix ?? (matrix = binarizer.BlackMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// Whether this bitmap can be cropped.
|
||||
/// </returns>
|
||||
public bool CropSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return binarizer.LuminanceSource.CropSupported;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
/// original data rather than a copy. Only callable if isCropSupported() is true.
|
||||
/// </summary>
|
||||
/// <param name="left">The left coordinate, which must be in [0, Width)</param>
|
||||
/// <param name="top">The top coordinate, which must be in [0, Height)</param>
|
||||
/// <param name="width">The width of the rectangle to crop.</param>
|
||||
/// <param name="height">The height of the rectangle to crop.</param>
|
||||
/// <returns> A cropped version of this object.</returns>
|
||||
public BinaryBitmap crop(int left, int top, int width, int height)
|
||||
{
|
||||
var newSource = binarizer.LuminanceSource.crop(left, top, width, height);
|
||||
return new BinaryBitmap(binarizer.createBinarizer(newSource));
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// Whether this bitmap supports counter-clockwise rotation.
|
||||
/// </returns>
|
||||
public bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return binarizer.LuminanceSource.RotateSupported;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
/// Only callable if <see cref="RotateSupported"/> is true.
|
||||
/// </summary>
|
||||
/// <returns>A rotated version of this object.</returns>
|
||||
public BinaryBitmap rotateCounterClockwise()
|
||||
{
|
||||
var newSource = binarizer.LuminanceSource.rotateCounterClockwise();
|
||||
return new BinaryBitmap(binarizer.createBinarizer(newSource));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 45 degrees counterclockwise.
|
||||
/// Only callable if <see cref="RotateSupported"/> is true.
|
||||
/// </summary>
|
||||
/// <returns>A rotated version of this object.</returns>
|
||||
public BinaryBitmap rotateCounterClockwise45()
|
||||
{
|
||||
LuminanceSource newSource = binarizer.LuminanceSource.rotateCounterClockwise45();
|
||||
return new BinaryBitmap(binarizer.createBinarizer(newSource));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var blackMatrix = BlackMatrix;
|
||||
return blackMatrix != null ? blackMatrix.ToString() : String.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
565
Others/zxing.core/zxing.core/BitmapLuminanceSource.cs
Normal file
565
Others/zxing.core/zxing.core/BitmapLuminanceSource.cs
Normal file
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
* 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.Imaging;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// class which represents the luminance values for a bitmap object
|
||||
/// </summary>
|
||||
public partial class BitmapLuminanceSource : BaseLuminanceSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BitmapLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapLuminanceSource"/> class
|
||||
/// with the image of a Bitmap instance
|
||||
/// </summary>
|
||||
/// <param name="bitmap">The bitmap.</param>
|
||||
public BitmapLuminanceSource(Bitmap bitmap)
|
||||
: base(bitmap.Width, bitmap.Height)
|
||||
{
|
||||
CalculateLuminanceValues(bitmap, luminances);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculates the luminance values for bitmaps
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="luminances"></param>
|
||||
protected static void CalculateLuminanceValues(Bitmap bitmap, byte[] luminances)
|
||||
{
|
||||
var height = bitmap.Height;
|
||||
var width = bitmap.Width;
|
||||
|
||||
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
|
||||
// The underlying raster of image consists of bytes with the luminance values
|
||||
#if WindowsCE
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
|
||||
#else
|
||||
var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
|
||||
#endif
|
||||
try
|
||||
{
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
|
||||
if (pixelWidth > 4)
|
||||
{
|
||||
// old slow way for unsupported bit depth
|
||||
CalculateLuminanceValuesSlow(bitmap, luminances);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !WindowsCE
|
||||
if (bitmap.PixelFormat == PixelFormat.Format32bppArgb ||
|
||||
bitmap.PixelFormat == PixelFormat.Format32bppPArgb)
|
||||
{
|
||||
pixelWidth = 40;
|
||||
}
|
||||
if ((int)bitmap.PixelFormat == 8207 ||
|
||||
(bitmap.Flags & (int)ImageFlags.ColorSpaceCmyk) == (int)ImageFlags.ColorSpaceCmyk)
|
||||
{
|
||||
pixelWidth = 41;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (pixelWidth)
|
||||
{
|
||||
#if !WindowsCE
|
||||
case 0:
|
||||
if (bitmap.PixelFormat == PixelFormat.Format4bppIndexed)
|
||||
CalculateLuminanceValuesForIndexed4Bit(bitmap, data, luminances);
|
||||
else
|
||||
CalculateLuminanceValuesForIndexed1Bit(bitmap, data, luminances);
|
||||
break;
|
||||
case 1:
|
||||
CalculateLuminanceValuesForIndexed8Bit(bitmap, data, luminances);
|
||||
break;
|
||||
#endif
|
||||
case 2:
|
||||
// should be RGB565 or RGB555, assume RGB565
|
||||
CalculateLuminanceValues565(bitmap, data, luminances);
|
||||
break;
|
||||
case 3:
|
||||
CalculateLuminanceValues24Bit(bitmap, data, luminances);
|
||||
break;
|
||||
case 4:
|
||||
CalculateLuminanceValues32BitWithoutAlpha(bitmap, data, luminances);
|
||||
break;
|
||||
case 40:
|
||||
CalculateLuminanceValues32BitWithAlpha(bitmap, data, luminances);
|
||||
break;
|
||||
case 41:
|
||||
CalculateLuminanceValues32BitCMYK(bitmap, data, luminances);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(data);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// old slow way for unsupported bit depth
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="luminances"></param>
|
||||
protected static void CalculateLuminanceValuesSlow(Bitmap bitmap, byte[] luminances)
|
||||
{
|
||||
var height = bitmap.Height;
|
||||
var width = bitmap.Width;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int offset = y * width;
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
var c = bitmap.GetPixel(x, y);
|
||||
luminances[offset + x] = (byte)((RChannelWeight * c.R + GChannelWeight * c.G + BChannelWeight * c.B) >> ChannelWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !WindowsCE
|
||||
/// <summary>
|
||||
/// calculates the luminance values for 1-bit indexed bitmaps
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="luminances"></param>
|
||||
protected static void CalculateLuminanceValuesForIndexed1Bit(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
|
||||
if (pixelWidth != 0)
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
|
||||
// prepare palette for 1, 4 and 8 bit indexed bitmaps
|
||||
var luminancePalette = new byte[256];
|
||||
var luminancePaletteLength = Math.Min(bitmap.Palette.Entries.Length, luminancePalette.Length);
|
||||
for (var index = 0; index < luminancePaletteLength; index++)
|
||||
{
|
||||
var color = bitmap.Palette.Entries[index];
|
||||
luminancePalette[index] = (byte)((RChannelWeight * color.R +
|
||||
GChannelWeight * color.G +
|
||||
BChannelWeight * color.B) >> ChannelWeight);
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
for (int x = 0; x * 8 < width; x++)
|
||||
{
|
||||
var x8 = 8 * x;
|
||||
var offset8 = offset + x8;
|
||||
for (int subX = 0; subX < 8 && x8 + subX < width; subX++)
|
||||
{
|
||||
var index = (buffer[x] >> (7 - subX)) & 1;
|
||||
luminances[offset8 + subX] = luminancePalette[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculates the luminance values for 4-bit indexed bitmaps
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="luminances"></param>
|
||||
protected static void CalculateLuminanceValuesForIndexed4Bit(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
if (bitmap.PixelFormat != PixelFormat.Format4bppIndexed)
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
var evenWidth = (width / 2) * 2;
|
||||
|
||||
if (pixelWidth != 0)
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
|
||||
// prepare palette for 1, 4 and 8 bit indexed bitmaps
|
||||
var luminancePalette = new byte[256];
|
||||
var luminancePaletteLength = Math.Min(bitmap.Palette.Entries.Length, luminancePalette.Length);
|
||||
for (var index = 0; index < luminancePaletteLength; index++)
|
||||
{
|
||||
var color = bitmap.Palette.Entries[index];
|
||||
luminancePalette[index] = (byte)((RChannelWeight * color.R +
|
||||
GChannelWeight * color.G +
|
||||
BChannelWeight * color.B) >> ChannelWeight);
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
int sourceX = 0;
|
||||
int destX = 0;
|
||||
byte sourceValue = 0;
|
||||
for (; destX < evenWidth; sourceX++, destX += 2)
|
||||
{
|
||||
sourceValue = buffer[sourceX];
|
||||
var index = sourceValue & 15;
|
||||
luminances[offset + destX + 1] = luminancePalette[index];
|
||||
index = (sourceValue >> 4) & 15;
|
||||
luminances[offset + destX] = luminancePalette[index];
|
||||
}
|
||||
if (width > evenWidth)
|
||||
{
|
||||
var index = (sourceValue >> 4) & 15;
|
||||
luminances[offset + destX] = luminancePalette[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculates the luminance values for 8-bit indexed bitmaps
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="luminances"></param>
|
||||
protected static void CalculateLuminanceValuesForIndexed8Bit(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
|
||||
if (pixelWidth != 1)
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
|
||||
// prepare palette for 1, 4 and 8 bit indexed bitmaps
|
||||
var luminancePalette = new byte[256];
|
||||
var luminancePaletteLength = Math.Min(bitmap.Palette.Entries.Length, luminancePalette.Length);
|
||||
for (var index = 0; index < luminancePaletteLength; index++)
|
||||
{
|
||||
var color = bitmap.Palette.Entries[index];
|
||||
luminancePalette[index] = (byte)((RChannelWeight * color.R +
|
||||
GChannelWeight * color.G +
|
||||
BChannelWeight * color.B) >> ChannelWeight);
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
luminances[offset + x] = luminancePalette[buffer[x]];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// calculates the luminance values for 565 encoded bitmaps
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="luminances"></param>
|
||||
private static void CalculateLuminanceValues565(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
|
||||
if (pixelWidth != 2)
|
||||
#if !WindowsCE
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
#else
|
||||
throw new InvalidOperationException("Unsupported pixel format");
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
var maxIndex = 2 * width;
|
||||
for (int index = 0; index < maxIndex; index += 2)
|
||||
{
|
||||
var byte1 = buffer[index];
|
||||
var byte2 = buffer[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;
|
||||
|
||||
luminances[offset] = (byte)((RChannelWeight * r8 + GChannelWeight * g8 + BChannelWeight * b8) >> ChannelWeight);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculates the luminance values for 24-bit encoded bitmaps
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="luminances"></param>
|
||||
private static void CalculateLuminanceValues24Bit(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
|
||||
if (pixelWidth != 3)
|
||||
#if !WindowsCE
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
#else
|
||||
throw new InvalidOperationException("Unsupported pixel format");
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
var maxIndex = width * 3;
|
||||
for (int x = 0; x < maxIndex; x += 3)
|
||||
{
|
||||
var luminance = (byte)((BChannelWeight * buffer[x] +
|
||||
GChannelWeight * buffer[x + 1] +
|
||||
RChannelWeight * buffer[x + 2]) >> ChannelWeight);
|
||||
luminances[offset] = luminance;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculates the luminance values for 32-bit encoded bitmaps without respecting the alpha channel
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="luminances"></param>
|
||||
private static void CalculateLuminanceValues32BitWithoutAlpha(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
var maxIndex = 4 * width;
|
||||
|
||||
if (pixelWidth != 4)
|
||||
#if !WindowsCE
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
#else
|
||||
throw new InvalidOperationException("Unsupported pixel format");
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
// 4 bytes without alpha channel value
|
||||
for (int x = 0; x < maxIndex; x += 4)
|
||||
{
|
||||
var luminance = (byte)((BChannelWeight * buffer[x] +
|
||||
GChannelWeight * buffer[x + 1] +
|
||||
RChannelWeight * buffer[x + 2]) >> ChannelWeight);
|
||||
|
||||
luminances[offset] = luminance;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// calculates the luminance values for 32-bit encoded bitmaps with alpha channel
|
||||
private static void CalculateLuminanceValues32BitWithAlpha(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
var maxIndex = 4 * width;
|
||||
|
||||
if (pixelWidth != 4)
|
||||
#if !WindowsCE
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
#else
|
||||
throw new InvalidOperationException("Unsupported pixel format");
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
// with alpha channel; some barcodes are completely black if you
|
||||
// only look at the r, g and b channel but the alpha channel controls
|
||||
// the view
|
||||
for (int x = 0; x < maxIndex; x += 4)
|
||||
{
|
||||
var luminance = (byte)((BChannelWeight * buffer[x] +
|
||||
GChannelWeight * buffer[x + 1] +
|
||||
RChannelWeight * buffer[x + 2]) >> ChannelWeight);
|
||||
|
||||
// calculating the resulting luminance based upon a white background
|
||||
// var alpha = buffer[x * pixelWidth + 3] / 255.0;
|
||||
// luminance = (byte)(luminance * alpha + 255 * (1 - alpha));
|
||||
var alpha = buffer[x + 3];
|
||||
luminance = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8) + 1);
|
||||
luminances[offset] = luminance;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// calculates the luminance values for 32-bit CMYK encoded bitmaps (k is ignored at the momen)
|
||||
private static void CalculateLuminanceValues32BitCMYK(Bitmap bitmap, BitmapData data, byte[] luminances)
|
||||
{
|
||||
var height = data.Height;
|
||||
var width = data.Width;
|
||||
var stride = Math.Abs(data.Stride);
|
||||
var pixelWidth = stride / width;
|
||||
var strideStep = data.Stride;
|
||||
var buffer = new byte[stride];
|
||||
var ptrInBitmap = data.Scan0;
|
||||
var maxIndex = 4 * width;
|
||||
|
||||
if (pixelWidth != 4)
|
||||
#if !WindowsCE
|
||||
throw new InvalidOperationException("Unsupported pixel format: " + bitmap.PixelFormat);
|
||||
#else
|
||||
throw new InvalidOperationException("Unsupported pixel format");
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
// copy a scanline not the whole bitmap because of memory usage
|
||||
Marshal.Copy(ptrInBitmap, buffer, 0, stride);
|
||||
#if NET40 || NET45 || NET46 || NET47 || NET48
|
||||
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
|
||||
#else
|
||||
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
|
||||
#endif
|
||||
var offset = y * width;
|
||||
for (int x = 0; x < maxIndex; x += 4)
|
||||
{
|
||||
var luminance = (byte)(255 - ((BChannelWeight * buffer[x] +
|
||||
GChannelWeight * buffer[x + 1] +
|
||||
RChannelWeight * buffer[x + 2]) >> ChannelWeight));
|
||||
// Ignore value of k at the moment
|
||||
luminances[offset] = luminance;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height)
|
||||
{
|
||||
return new BitmapLuminanceSource(width, height) { luminances = newLuminances };
|
||||
}
|
||||
}
|
||||
}
|
||||
202
Others/zxing.core/zxing.core/BitmapSourceLuminanceSource.cs
Normal file
202
Others/zxing.core/zxing.core/BitmapSourceLuminanceSource.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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.Windows;
|
||||
#if NETFX_CORE
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// class which represents the luminance source values for bitmap source objects
|
||||
/// </summary>
|
||||
public partial class BitmapSourceLuminanceSource : BaseLuminanceSource
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapSourceLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected BitmapSourceLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BitmapSourceLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="bitmap">The bitmap.</param>
|
||||
public BitmapSourceLuminanceSource(BitmapSource bitmap)
|
||||
: base(bitmap.PixelWidth, bitmap.PixelHeight)
|
||||
{
|
||||
switch (bitmap.Format.ToString())
|
||||
{
|
||||
case "Bgr24":
|
||||
case "Bgr32":
|
||||
CalculateLuminanceBGR(bitmap);
|
||||
break;
|
||||
case "Bgra32":
|
||||
CalculateLuminanceBGRA(bitmap);
|
||||
break;
|
||||
case "Rgb24":
|
||||
CalculateLuminanceRGB(bitmap);
|
||||
break;
|
||||
case "Bgr565":
|
||||
CalculateLuminanceBGR565(bitmap);
|
||||
break;
|
||||
default:
|
||||
// there is no special conversion routine to luminance values
|
||||
// we have to convert the image to a supported format
|
||||
bitmap = new FormatConvertedBitmap(bitmap, PixelFormats.Bgra32, null, 0);
|
||||
CalculateLuminanceBGR(bitmap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLuminanceRGB(BitmapSource bitmap)
|
||||
{
|
||||
var width = bitmap.PixelWidth;
|
||||
var height = bitmap.PixelHeight;
|
||||
var stepX = (bitmap.Format.BitsPerPixel + 7) / 8;
|
||||
var bufferSize = width * stepX;
|
||||
var buffer = new byte[bufferSize];
|
||||
var rect = new Int32Rect(0, 0, width, 1);
|
||||
var luminanceIndex = 0;
|
||||
|
||||
for (var curY = 0; curY < height; curY++)
|
||||
{
|
||||
bitmap.CopyPixels(rect, buffer, bufferSize, 0);
|
||||
for (var curX = 0; curX < bufferSize; curX += stepX)
|
||||
{
|
||||
var r = buffer[curX];
|
||||
var g = buffer[curX + 1];
|
||||
var b = buffer[curX + 2];
|
||||
luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
|
||||
luminanceIndex++;
|
||||
}
|
||||
rect.Y++;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLuminanceBGR(BitmapSource bitmap)
|
||||
{
|
||||
var width = bitmap.PixelWidth;
|
||||
var height = bitmap.PixelHeight;
|
||||
var stepX = (bitmap.Format.BitsPerPixel + 7) / 8;
|
||||
var bufferSize = width * stepX;
|
||||
var buffer = new byte[bufferSize];
|
||||
var rect = new Int32Rect(0, 0, width, 1);
|
||||
var luminanceIndex = 0;
|
||||
|
||||
for (var curY = 0; curY < height; curY++)
|
||||
{
|
||||
bitmap.CopyPixels(rect, buffer, bufferSize, 0);
|
||||
for (var curX = 0; curX < bufferSize; curX += stepX)
|
||||
{
|
||||
var b = buffer[curX];
|
||||
var g = buffer[curX + 1];
|
||||
var r = buffer[curX + 2];
|
||||
luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
|
||||
luminanceIndex++;
|
||||
}
|
||||
rect.Y++;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLuminanceBGRA(BitmapSource bitmap)
|
||||
{
|
||||
var width = bitmap.PixelWidth;
|
||||
var height = bitmap.PixelHeight;
|
||||
var stepX = (bitmap.Format.BitsPerPixel + 7) / 8;
|
||||
var bufferSize = width * stepX;
|
||||
var buffer = new byte[bufferSize];
|
||||
var rect = new Int32Rect(0, 0, width, 1);
|
||||
var luminanceIndex = 0;
|
||||
|
||||
for (var curY = 0; curY < height; curY++)
|
||||
{
|
||||
bitmap.CopyPixels(rect, buffer, bufferSize, 0);
|
||||
for (var curX = 0; curX < bufferSize; curX += stepX)
|
||||
{
|
||||
var b = buffer[curX];
|
||||
var g = buffer[curX + 1];
|
||||
var r = buffer[curX + 2];
|
||||
var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
|
||||
var alpha = buffer[curX + 3];
|
||||
luminance = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8));
|
||||
luminances[luminanceIndex] = luminance;
|
||||
luminanceIndex++;
|
||||
}
|
||||
rect.Y++;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLuminanceBGR565(BitmapSource bitmap)
|
||||
{
|
||||
var width = bitmap.PixelWidth;
|
||||
var height = bitmap.PixelHeight;
|
||||
var stepX = (bitmap.Format.BitsPerPixel + 7) / 8;
|
||||
var bufferSize = width * stepX;
|
||||
var buffer = new byte[bufferSize];
|
||||
var rect = new Int32Rect(0, 0, width, 1);
|
||||
var luminanceIndex = 0;
|
||||
|
||||
for (var curY = 0; curY < height; curY++)
|
||||
{
|
||||
bitmap.CopyPixels(rect, buffer, bufferSize, 0);
|
||||
for (var curX = 0; curX < bufferSize; curX += stepX)
|
||||
{
|
||||
var byte1 = buffer[curX];
|
||||
var byte2 = buffer[curX + 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);
|
||||
luminanceIndex++;
|
||||
}
|
||||
rect.Y++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height)
|
||||
{
|
||||
return new BitmapSourceLuminanceSource(width, height) { luminances = newLuminances };
|
||||
}
|
||||
}
|
||||
}
|
||||
125
Others/zxing.core/zxing.core/DecodeHintType.cs
Normal file
125
Others/zxing.core/zxing.core/DecodeHintType.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates a type of hint that a caller may pass to a barcode reader to help it
|
||||
/// more quickly or accurately decode it. It is up to implementations to decide what,
|
||||
/// if anything, to do with the information that is supplied.
|
||||
/// <seealso cref="Reader.decode(BinaryBitmap, IDictionary{DecodeHintType, object})" />
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
public enum DecodeHintType
|
||||
{
|
||||
/// <summary>
|
||||
/// Unspecified, application-specific hint. Maps to an unspecified <see cref="System.Object" />.
|
||||
/// </summary>
|
||||
OTHER,
|
||||
|
||||
/// <summary>
|
||||
/// Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
|
||||
/// use <see cref="bool" /> = true.
|
||||
/// </summary>
|
||||
PURE_BARCODE,
|
||||
|
||||
/// <summary>
|
||||
/// Image is known to be of one of a few possible formats.
|
||||
/// Maps to a <see cref="System.Collections.ICollection" /> of <see cref="BarcodeFormat" />s.
|
||||
/// </summary>
|
||||
POSSIBLE_FORMATS,
|
||||
|
||||
/// <summary>
|
||||
/// Spend more time to try to find a barcode; optimize for accuracy, not speed.
|
||||
/// Doesn't matter what it maps to; use <see cref="bool" /> = true.
|
||||
/// </summary>
|
||||
TRY_HARDER,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what character encoding to use when decoding, where applicable (type String)
|
||||
/// </summary>
|
||||
CHARACTER_SET,
|
||||
|
||||
/// <summary>
|
||||
/// Allowed lengths of encoded data -- reject anything else. Maps to an int[].
|
||||
/// </summary>
|
||||
ALLOWED_LENGTHS,
|
||||
|
||||
/// <summary>
|
||||
/// Assume Code 39 codes employ a check digit. Maps to <see cref="bool" />.
|
||||
/// </summary>
|
||||
ASSUME_CODE_39_CHECK_DIGIT,
|
||||
|
||||
/// <summary>
|
||||
/// The caller needs to be notified via callback when a possible <see cref="ResultPoint" />
|
||||
/// is found. Maps to a <see cref="ResultPointCallback" />.
|
||||
/// </summary>
|
||||
NEED_RESULT_POINT_CALLBACK,
|
||||
|
||||
/// <summary>
|
||||
/// Assume MSI codes employ a check digit. Maps to <see cref="bool" />.
|
||||
/// </summary>
|
||||
ASSUME_MSI_CHECK_DIGIT,
|
||||
|
||||
/// <summary>
|
||||
/// if Code39 could be detected try to use extended mode for full ASCII character set
|
||||
/// Maps to <see cref="bool" />.
|
||||
/// </summary>
|
||||
USE_CODE_39_EXTENDED_MODE,
|
||||
|
||||
/// <summary>
|
||||
/// Don't fail if a Code39 is detected but can't be decoded in extended mode.
|
||||
/// Return the raw Code39 result instead. Maps to <see cref="bool" />.
|
||||
/// </summary>
|
||||
RELAXED_CODE_39_EXTENDED_MODE,
|
||||
|
||||
/// <summary>
|
||||
/// 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 <see cref="bool" />.
|
||||
/// </summary>
|
||||
TRY_HARDER_WITHOUT_ROTATION,
|
||||
|
||||
/// <summary>
|
||||
/// 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 <see cref="bool" />.
|
||||
/// </summary>
|
||||
ASSUME_GS1,
|
||||
|
||||
/// <summary>
|
||||
/// If true, return the start and end digits in a Codabar barcode instead of stripping them. They
|
||||
/// are alpha, whereas the rest are numeric. By default, they are stripped, but this causes them
|
||||
/// to not be. Doesn't matter what it maps to; use <see cref="bool" />.
|
||||
/// </summary>
|
||||
RETURN_CODABAR_START_END,
|
||||
|
||||
/// <summary>
|
||||
/// Allowed extension lengths for EAN or UPC barcodes. Other formats will ignore this.
|
||||
/// Maps to an int[] 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.
|
||||
/// </summary>
|
||||
ALLOWED_EAN_EXTENSIONS
|
||||
}
|
||||
}
|
||||
93
Others/zxing.core/zxing.core/Dimension.cs
Normal file
93
Others/zxing.core/zxing.core/Dimension.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Simply encapsulates a width and height.
|
||||
/// </summary>
|
||||
public sealed class Dimension
|
||||
{
|
||||
private readonly int width;
|
||||
private readonly int height;
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
public Dimension(int width, int height)
|
||||
{
|
||||
if (width < 0 || height < 0)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the width
|
||||
/// </summary>
|
||||
public int Width
|
||||
{
|
||||
get { return width; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the height
|
||||
/// </summary>
|
||||
public int Height
|
||||
{
|
||||
get { return height; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(Object other)
|
||||
{
|
||||
if (other is Dimension)
|
||||
{
|
||||
var d = (Dimension)other;
|
||||
return width == d.width && height == d.height;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return width * 32713 + height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return width + "x" + height;
|
||||
}
|
||||
}
|
||||
}
|
||||
174
Others/zxing.core/zxing.core/EncodeHintType.cs
Normal file
174
Others/zxing.core/zxing.core/EncodeHintType.cs
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// These are a set of hints that you may pass to Writers to specify their behavior.
|
||||
/// </summary>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
public enum EncodeHintType
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the width of the barcode image
|
||||
/// type: <see cref="System.Int32" />
|
||||
/// </summary>
|
||||
WIDTH,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the height of the barcode image
|
||||
/// type: <see cref="System.Int32" />
|
||||
/// </summary>
|
||||
HEIGHT,
|
||||
|
||||
/// <summary>
|
||||
/// Don't put the content string into the output image.
|
||||
/// type: <see cref="System.Boolean" />
|
||||
/// </summary>
|
||||
PURE_BARCODE,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what degree of error correction to use, for example in QR Codes.
|
||||
/// Type depends on the encoder. For example for QR codes it's type
|
||||
/// <see cref="ZXing.QrCode.Internal.ErrorCorrectionLevel" />
|
||||
/// For Aztec it is of type <see cref="System.Int32" />, representing the minimal percentage of error correction words.
|
||||
/// In all cases, it can also be a <see cref="System.String" /> representation of the desired value as well.
|
||||
/// Note: an Aztec symbol should have a minimum of 25% EC words.
|
||||
/// For PDF417 it is of type <see cref="ZXing.PDF417.Internal.PDF417ErrorCorrectionLevel"/> or <see cref="System.Int32" /> (between 0 and 8),
|
||||
/// </summary>
|
||||
ERROR_CORRECTION,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what character encoding to use where applicable.
|
||||
/// type: <see cref="System.String" />
|
||||
/// </summary>
|
||||
CHARACTER_SET,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies margin, in pixels, to use when generating the barcode. The meaning can vary
|
||||
/// by format; for example it controls margin before and after the barcode horizontally for
|
||||
/// most 1D formats.
|
||||
/// type: <see cref="System.Int32" />, or <see cref="System.String" /> representation of the integer value
|
||||
/// </summary>
|
||||
MARGIN,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the aspect ratio to use. Default is 4.
|
||||
/// type: <see cref="ZXing.PDF417.Internal.PDF417AspectRatio" />, or 1-4.
|
||||
/// </summary>
|
||||
PDF417_ASPECT_RATIO,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the desired aspect ratio (number of columns / number of rows) of the output image. Default is 3.
|
||||
/// type: <see cref="System.Single" />.
|
||||
/// </summary>
|
||||
PDF417_IMAGE_ASPECT_RATIO,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to use compact mode for PDF417
|
||||
/// type: <see cref="System.Boolean" />, or "true" or "false"
|
||||
/// <see cref="System.String" /> value
|
||||
/// </summary>
|
||||
PDF417_COMPACT,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what compaction mode to use for PDF417.
|
||||
/// type: <see cref="ZXing.PDF417.Internal.Compaction" /> or <see cref="System.String" /> value of one of its
|
||||
/// enum values
|
||||
/// </summary>
|
||||
PDF417_COMPACTION,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the minimum and maximum number of rows and columns for PDF417.
|
||||
/// type: <see cref="ZXing.PDF417.Internal.Dimensions" />
|
||||
/// </summary>
|
||||
PDF417_DIMENSIONS,
|
||||
|
||||
/// <summary>
|
||||
/// The Specifies that the PDF417 will contain macro metadata.
|
||||
/// type: <see cref="ZXing.PDF417.PDF417MacroMetadata"/>
|
||||
/// </summary>
|
||||
PDF417_MACRO_META_DATA,
|
||||
|
||||
/// <summary>
|
||||
/// 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: <see cref="System.Boolean" />
|
||||
/// </summary>
|
||||
DISABLE_ECI,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the matrix shape for Data Matrix (type <see cref="ZXing.Datamatrix.Encoder.SymbolShapeHint"/>)
|
||||
/// </summary>
|
||||
DATA_MATRIX_SHAPE,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a minimum barcode size (type <see cref="ZXing.Dimension"/>). Only applicable to Data Matrix now.
|
||||
/// </summary>
|
||||
MIN_SIZE,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a maximum barcode size (type <see cref="ZXing.Dimension"/>). Only applicable to Data Matrix now.
|
||||
/// </summary>
|
||||
MAX_SIZE,
|
||||
|
||||
/// <summary>
|
||||
/// if true, don't switch to codeset C for numbers
|
||||
/// </summary>
|
||||
CODE128_FORCE_CODESET_B,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the default encodation for Data Matrix (type <see cref="ZXing.Datamatrix.Encoder.Encodation"/>)
|
||||
/// Make sure that the content fits into the encodation value, otherwise there will be an exception thrown.
|
||||
/// standard value: Encodation.ASCII
|
||||
/// </summary>
|
||||
DATA_MATRIX_DEFAULT_ENCODATION,
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// type: <see cref="System.Int32" />, or <see cref="System.String" /> representation of the integer value
|
||||
/// </summary>
|
||||
AZTEC_LAYERS,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the exact version of QR code to be encoded.
|
||||
/// (Type <see cref="System.Int32" />, or <see cref="System.String" /> representation of the integer value).
|
||||
/// </summary>
|
||||
QR_VERSION,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether the data should be encoded to the GS1 standard
|
||||
/// type: <see cref="System.Boolean" />, or "true" or "false"
|
||||
/// <see cref="System.String" /> value
|
||||
/// </summary>
|
||||
GS1_FORMAT,
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the QR code mask pattern to be used. Allowed values are
|
||||
/// 0..QRCode.NUM_MASK_PATTERNS-1. By default the code will automatically select
|
||||
/// the optimal mask pattern.
|
||||
/// (Type <see cref="System.Int32" />, or <see cref="System.String" /> representation of the integer value).
|
||||
/// </summary>
|
||||
QR_MASK_PATTERN,
|
||||
}
|
||||
}
|
||||
60
Others/zxing.core/zxing.core/FormatException.cs
Normal file
60
Others/zxing.core/zxing.core/FormatException.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// <author>Sean Owen</author>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class FormatException : ReaderException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public FormatException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public FormatException(String message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public FormatException(Exception innerException)
|
||||
: base(innerException)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public FormatException(String message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Others/zxing.core/zxing.core/IBarcodeReader.Bitmap.cs
Normal file
33
Others/zxing.core/zxing.core/IBarcodeReader.Bitmap.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012 ZXing.Net authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to decode the barcode inside a bitmap object
|
||||
/// </summary>
|
||||
public partial interface IBarcodeReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap.
|
||||
/// </summary>
|
||||
/// <param name="barcodeBitmap">The barcode bitmap.</param>
|
||||
/// <returns>the result data or null</returns>
|
||||
Result Decode(System.Drawing.Bitmap barcodeBitmap);
|
||||
}
|
||||
}
|
||||
47
Others/zxing.core/zxing.core/IBarcodeReader.Multiple.cs
Normal file
47
Others/zxing.core/zxing.core/IBarcodeReader.Multiple.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to decode multiple barcodes inside a bitmap object
|
||||
/// </summary>
|
||||
public partial interface IBarcodeReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap which is given by a generic byte array with the order RGB24.
|
||||
/// </summary>
|
||||
/// <param name="rawRGB">The image as RGB24 array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <returns>
|
||||
/// the result data or null
|
||||
/// </returns>
|
||||
Result[] DecodeMultiple(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format);
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="luminanceSource">The luminance source.</param>
|
||||
/// <returns></returns>
|
||||
Result[] DecodeMultiple(LuminanceSource luminanceSource);
|
||||
}
|
||||
}
|
||||
66
Others/zxing.core/zxing.core/IBarcodeReader.cs
Normal file
66
Others/zxing.core/zxing.core/IBarcodeReader.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to decode the barcode inside a bitmap object
|
||||
/// </summary>
|
||||
public partial interface IBarcodeReader
|
||||
{
|
||||
/// <summary>
|
||||
/// event is executed when a result point was found
|
||||
/// </summary>
|
||||
event Action<ResultPoint> ResultPointFound;
|
||||
|
||||
/// <summary>
|
||||
/// event is executed when a result was found via decode
|
||||
/// </summary>
|
||||
event Action<Result> ResultFound;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies some options which influence the decoding process
|
||||
/// </summary>
|
||||
DecodingOptions Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap which is given by a generic byte array with the order RGB24.
|
||||
/// </summary>
|
||||
/// <param name="rawRGB">The image as RGB24 array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <returns>
|
||||
/// the result data or null
|
||||
/// </returns>
|
||||
Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to decode a barcode within an image which is given by a luminance source.
|
||||
/// That method gives a chance to prepare a luminance source completely before calling
|
||||
/// the time consuming decoding method. On the other hand there is a chance to create
|
||||
/// a luminance source which is independent from external resources (like Bitmap objects)
|
||||
/// and the decoding call can be made in a background thread.
|
||||
/// </summary>
|
||||
/// <param name="luminanceSource">The luminance source.</param>
|
||||
/// <returns></returns>
|
||||
Result Decode(LuminanceSource luminanceSource);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to decode multiple barcodes inside a bitmap object
|
||||
/// </summary>
|
||||
public partial interface IBarcodeReader<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap.
|
||||
/// </summary>
|
||||
/// <param name="barcodeBitmap">The barcode bitmap.</param>
|
||||
/// <returns>the result data or null</returns>
|
||||
Result[] DecodeMultiple(T barcodeBitmap);
|
||||
}
|
||||
}
|
||||
31
Others/zxing.core/zxing.core/IBarcodeReaderCustom.cs
Normal file
31
Others/zxing.core/zxing.core/IBarcodeReaderCustom.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to decode the barcode inside a bitmap object
|
||||
/// </summary>
|
||||
public partial interface IBarcodeReader<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap.
|
||||
/// </summary>
|
||||
/// <param name="barcodeBitmap">The barcode bitmap.</param>
|
||||
/// <returns>the result data or null</returns>
|
||||
Result Decode(T barcodeBitmap);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to decode multiple barcodes inside a bitmap object
|
||||
/// </summary>
|
||||
public partial interface IBarcodeReaderGeneric
|
||||
{
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap which is given by a generic byte array with the order RGB24.
|
||||
/// </summary>
|
||||
/// <param name="rawRGB">The barcode bitmap.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <returns>
|
||||
/// the result data or null
|
||||
/// </returns>
|
||||
Result[] DecodeMultiple(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format);
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="luminanceSource">The luminance source.</param>
|
||||
/// <returns></returns>
|
||||
Result[] DecodeMultiple(LuminanceSource luminanceSource);
|
||||
}
|
||||
}
|
||||
66
Others/zxing.core/zxing.core/IBarcodeReaderGeneric.cs
Normal file
66
Others/zxing.core/zxing.core/IBarcodeReaderGeneric.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to decode the barcode inside a bitmap object
|
||||
/// </summary>
|
||||
public partial interface IBarcodeReaderGeneric
|
||||
{
|
||||
/// <summary>
|
||||
/// event is executed when a result point was found
|
||||
/// </summary>
|
||||
event Action<ResultPoint> ResultPointFound;
|
||||
|
||||
/// <summary>
|
||||
/// event is executed when a result was found via decode
|
||||
/// </summary>
|
||||
event Action<Result> ResultFound;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies some options which influence the decoding process
|
||||
/// </summary>
|
||||
DecodingOptions Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified barcode bitmap which is given by a generic byte array.
|
||||
/// </summary>
|
||||
/// <param name="rawRGB">The barcode bitmap.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <returns>
|
||||
/// the result data or null
|
||||
/// </returns>
|
||||
Result Decode(byte[] rawRGB, int width, int height, RGBLuminanceSource.BitmapFormat format);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to decode a barcode within an image which is given by a luminance source.
|
||||
/// That method gives a chance to prepare a luminance source completely before calling
|
||||
/// the time consuming decoding method. On the other hand there is a chance to create
|
||||
/// a luminance source which is independent from external resources (like Bitmap objects)
|
||||
/// and the decoding call can be made in a background thread.
|
||||
/// </summary>
|
||||
/// <param name="luminanceSource">The luminance source.</param>
|
||||
/// <returns></returns>
|
||||
Result Decode(LuminanceSource luminanceSource);
|
||||
}
|
||||
}
|
||||
35
Others/zxing.core/zxing.core/IBarcodeWriter.Bitmap.cs
Normal file
35
Others/zxing.core/zxing.core/IBarcodeWriter.Bitmap.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to encode some content into a barcode
|
||||
/// </summary>
|
||||
public partial interface IBarcodeWriter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a visual representation of the contents
|
||||
/// </summary>
|
||||
System.Drawing.Bitmap Write(string contents);
|
||||
/// <summary>
|
||||
/// Returns a rendered instance of the barcode which is given by a BitMatrix.
|
||||
/// </summary>
|
||||
System.Drawing.Bitmap Write(BitMatrix matrix);
|
||||
}
|
||||
}
|
||||
37
Others/zxing.core/zxing.core/IBarcodeWriter.PixelData.cs
Normal file
37
Others/zxing.core/zxing.core/IBarcodeWriter.PixelData.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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;
|
||||
using ZXing.Rendering;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to encode some content into a barcode
|
||||
/// </summary>
|
||||
public partial interface IBarcodeWriterPixelData
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a visual representation of the contents
|
||||
/// </summary>
|
||||
PixelData Write(string contents);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a rendered instance of the barcode which is given by a BitMatrix.
|
||||
/// </summary>
|
||||
PixelData Write(BitMatrix matrix);
|
||||
}
|
||||
}
|
||||
37
Others/zxing.core/zxing.core/IBarcodeWriter.SvgImage.cs
Normal file
37
Others/zxing.core/zxing.core/IBarcodeWriter.SvgImage.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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;
|
||||
using ZXing.Rendering;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to encode some content into a barcode
|
||||
/// </summary>
|
||||
public partial interface IBarcodeWriterSvg
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a visual representation of the contents
|
||||
/// </summary>
|
||||
SvgRenderer.SvgImage Write(string contents);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a rendered instance of the barcode which is given by a BitMatrix.
|
||||
/// </summary>
|
||||
SvgRenderer.SvgImage Write(BitMatrix matrix);
|
||||
}
|
||||
}
|
||||
50
Others/zxing.core/zxing.core/IBarcodeWriter.cs
Normal file
50
Others/zxing.core/zxing.core/IBarcodeWriter.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to encode some content into a barcode
|
||||
/// </summary>
|
||||
public partial interface IBarcodeWriter
|
||||
{
|
||||
/// <summary>
|
||||
/// Get or sets the barcode format which should be generated
|
||||
/// (only suitable if MultiFormatWriter is used for property Encoder which is the default)
|
||||
/// </summary>
|
||||
BarcodeFormat Format { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options container for the encoding and renderer process.
|
||||
/// </summary>
|
||||
EncodingOptions Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the writer which encodes the content to a BitMatrix.
|
||||
/// If no value is set the MultiFormatWriter is used.
|
||||
/// </summary>
|
||||
Writer Encoder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the specified contents.
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents.</param>
|
||||
/// <returns></returns>
|
||||
BitMatrix Encode(string contents);
|
||||
}
|
||||
}
|
||||
47
Others/zxing.core/zxing.core/IBarcodeWriterCustom.cs
Normal file
47
Others/zxing.core/zxing.core/IBarcodeWriterCustom.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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)
|
||||
/// <summary>
|
||||
/// Interface for a smart class to encode some content into a barcode
|
||||
/// </summary>
|
||||
public partial interface IBarcodeWriter<out TOutput>
|
||||
#else
|
||||
/// <summary>
|
||||
/// Interface for a smart class to encode some content into a barcode
|
||||
/// </summary>
|
||||
public interface IBarcodeWriter<TOutput>
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a visual representation of the contents
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents.</param>
|
||||
/// <returns></returns>
|
||||
TOutput Write(string contents);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a rendered instance of the barcode which is given by a BitMatrix.
|
||||
/// </summary>
|
||||
/// <param name="matrix">The matrix.</param>
|
||||
/// <returns></returns>
|
||||
TOutput Write(BitMatrix matrix);
|
||||
}
|
||||
}
|
||||
50
Others/zxing.core/zxing.core/IBarcodeWriterGeneric.cs
Normal file
50
Others/zxing.core/zxing.core/IBarcodeWriterGeneric.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for a smart class to encode some content into a barcode
|
||||
/// </summary>
|
||||
public interface IBarcodeWriterGeneric
|
||||
{
|
||||
/// <summary>
|
||||
/// Get or sets the barcode format which should be generated
|
||||
/// (only suitable if MultiFormatWriter is used for property Encoder which is the default)
|
||||
/// </summary>
|
||||
BarcodeFormat Format { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options container for the encoding and renderer process.
|
||||
/// </summary>
|
||||
EncodingOptions Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the writer which encodes the content to a BitMatrix.
|
||||
/// If no value is set the MultiFormatWriter is used.
|
||||
/// </summary>
|
||||
Writer Encoder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the specified contents.
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents.</param>
|
||||
/// <returns></returns>
|
||||
BitMatrix Encode(string contents);
|
||||
}
|
||||
}
|
||||
154
Others/zxing.core/zxing.core/InvertedLuminanceSource.cs
Normal file
154
Others/zxing.core/zxing.core/InvertedLuminanceSource.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// A wrapper implementation of {@link LuminanceSource} which inverts the luminances it returns -- black becomes
|
||||
/// white and vice versa, and each value becomes (255-value).
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class InvertedLuminanceSource : LuminanceSource
|
||||
{
|
||||
private readonly LuminanceSource @delegate;
|
||||
private byte[] invertedMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvertedLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="delegate">The @delegate.</param>
|
||||
public InvertedLuminanceSource(LuminanceSource @delegate)
|
||||
: base(@delegate.Width, @delegate.Height)
|
||||
{
|
||||
this.@delegate = @delegate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
/// 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
|
||||
/// to bitwise and with 0xff for each value. It is preferable for implementations of this method
|
||||
/// to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
/// getMatrix() may never be called.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, 0 <= y < Height.</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// Always use the returned object, and ignore the .length of the array.</param>
|
||||
/// <returns>
|
||||
/// An array containing the luminance data.
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
||||
/// int luminance = array[y * width + x] & 0xff;
|
||||
/// </summary>
|
||||
/// <returns> A row-major 2D array of luminance values. Do not use result.length as it may be
|
||||
/// larger than width * height bytes on some platforms. Do not modify the contents
|
||||
/// of the result.
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports cropping.</returns>
|
||||
override public bool CropSupported
|
||||
{
|
||||
get { return @delegate.CropSupported; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
/// original data rather than a copy. Only callable if CropSupported is true.
|
||||
/// </summary>
|
||||
/// <param name="left">The left coordinate, 0 <= left < Width.</param>
|
||||
/// <param name="top">The top coordinate, 0 <= top <= Height.</param>
|
||||
/// <param name="width">The width of the rectangle to crop.</param>
|
||||
/// <param name="height">The height of the rectangle to crop.</param>
|
||||
/// <returns>
|
||||
/// A cropped version of this object.
|
||||
/// </returns>
|
||||
override public LuminanceSource crop(int left, int top, int width, int height)
|
||||
{
|
||||
return new InvertedLuminanceSource(@delegate.crop(left, top, width, height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports counter-clockwise rotation.</returns>
|
||||
override public bool RotateSupported
|
||||
{
|
||||
get { return @delegate.RotateSupported; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inverts this instance.
|
||||
/// </summary>
|
||||
/// <returns>original delegate {@link LuminanceSource} since invert undoes itself</returns>
|
||||
override public LuminanceSource invert()
|
||||
{
|
||||
return @delegate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
/// Only callable if {@link #isRotateSupported()} is true.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A rotated version of this object.
|
||||
/// </returns>
|
||||
override public LuminanceSource rotateCounterClockwise()
|
||||
{
|
||||
return new InvertedLuminanceSource(@delegate.rotateCounterClockwise());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 45 degrees counterclockwise.
|
||||
/// Only callable if {@link #isRotateSupported()} is true.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A rotated version of this object.
|
||||
/// </returns>
|
||||
override public LuminanceSource rotateCounterClockwise45()
|
||||
{
|
||||
return new InvertedLuminanceSource(@delegate.rotateCounterClockwise45());
|
||||
}
|
||||
}
|
||||
}
|
||||
207
Others/zxing.core/zxing.core/LuminanceSource.cs
Normal file
207
Others/zxing.core/zxing.core/LuminanceSource.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// The purpose of this class hierarchy is to abstract different bitmap implementations across
|
||||
/// platforms into a standard interface for requesting greyscale luminance values. The interface
|
||||
/// only provides immutable methods; therefore crop and rotation create copies. This is to ensure
|
||||
/// that one Reader does not modify the original luminance source and leave it in an unknown state
|
||||
/// for other Readers in the chain.
|
||||
/// </summary>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
public abstract class LuminanceSource
|
||||
{
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
protected LuminanceSource(int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
/// 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
|
||||
/// to bitwise and with 0xff for each value. It is preferable for implementations of this method
|
||||
/// to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
/// getMatrix() may never be called.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, which must be in [0, bitmap height)</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// Always use the returned object, and ignore the .length of the array.
|
||||
/// </param>
|
||||
/// <returns> An array containing the luminance data.</returns>
|
||||
public abstract byte[] getRow(int y, byte[] row);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches luminance data for the underlying bitmap. Values should be fetched using:
|
||||
/// <code>int luminance = array[y * width + x] & 0xff</code>
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A row-major 2D array of luminance values. Do not use result.length as it may be
|
||||
/// larger than width * height bytes on some platforms. Do not modify the contents
|
||||
/// of the result.
|
||||
/// </returns>
|
||||
public abstract byte[] Matrix { get; }
|
||||
|
||||
/// <returns> The width of the bitmap.</returns>
|
||||
public virtual int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return width;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
width = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns> The height of the bitmap.</returns>
|
||||
public virtual int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return height;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
height = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns> Whether this subclass supports cropping.</returns>
|
||||
public virtual bool CropSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
/// original data rather than a copy. Only callable if CropSupported is true.
|
||||
/// </summary>
|
||||
/// <param name="left">The left coordinate, which must be in [0, Width)</param>
|
||||
/// <param name="top">The top coordinate, which must be in [0, Height)</param>
|
||||
/// <param name="width">The width of the rectangle to crop.</param>
|
||||
/// <param name="height">The height of the rectangle to crop.</param>
|
||||
/// <returns> A cropped version of this object.</returns>
|
||||
public virtual LuminanceSource crop(int left, int top, int width, int height)
|
||||
{
|
||||
throw new NotSupportedException("This luminance source does not support cropping.");
|
||||
}
|
||||
|
||||
/// <returns> Whether this subclass supports counter-clockwise rotation.</returns>
|
||||
public virtual bool RotateSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
|
||||
/// Only callable if <see cref="RotateSupported"/> is true.
|
||||
/// </summary>
|
||||
/// <returns>A rotated version of this object.</returns>
|
||||
public virtual LuminanceSource rotateCounterClockwise()
|
||||
{
|
||||
throw new NotSupportedException("This luminance source does not support rotation.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with rotated image data by 45 degrees counterclockwise.
|
||||
/// Only callable if <see cref="RotateSupported"/> is true.
|
||||
/// </summary>
|
||||
/// <returns>A rotated version of this object.</returns>
|
||||
public virtual LuminanceSource rotateCounterClockwise45()
|
||||
{
|
||||
throw new NotSupportedException("This luminance source does not support rotation by 45 degrees.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns>Whether this subclass supports invertion.</returns>
|
||||
public virtual bool InversionSupported
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// inverts the luminance values, not supported here. has to implemented in sub classes
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual LuminanceSource invert()
|
||||
{
|
||||
throw new NotSupportedException("This luminance source does not support inversion.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
229
Others/zxing.core/zxing.core/MultiFormatReader.cs
Normal file
229
Others/zxing.core/zxing.core/MultiFormatReader.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// MultiFormatReader is a convenience class and the main entry point into the library for most uses.
|
||||
/// By default it attempts to decode all barcode formats that the library supports. Optionally, you
|
||||
/// can provide a hints object to request different behavior, for example only decoding QR codes.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source</author>
|
||||
public sealed class MultiFormatReader : Reader
|
||||
{
|
||||
private IDictionary<DecodeHintType, object> hints;
|
||||
private IList<Reader> readers;
|
||||
|
||||
/// <summary> This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it
|
||||
/// passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.
|
||||
/// Use setHints() followed by decodeWithState() for continuous scan applications.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="image">The pixel data to decode
|
||||
/// </param>
|
||||
/// <returns> The contents of the image
|
||||
/// </returns>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
public Result decode(BinaryBitmap image)
|
||||
{
|
||||
Hints = null;
|
||||
return decodeInternal(image);
|
||||
}
|
||||
|
||||
/// <summary> Decode an image using the hints provided. Does not honor existing state.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="image">The pixel data to decode
|
||||
/// </param>
|
||||
/// <param name="hints">The hints to use, clearing the previous state.
|
||||
/// </param>
|
||||
/// <returns> The contents of the image
|
||||
/// </returns>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
|
||||
{
|
||||
Hints = hints;
|
||||
return decodeInternal(image);
|
||||
}
|
||||
|
||||
/// <summary> Decode an image using the state set up by calling setHints() previously. Continuous scan
|
||||
/// clients will get a <b>large</b> speed increase by using this instead of decode().
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="image">The pixel data to decode
|
||||
/// </param>
|
||||
/// <returns> The contents of the image
|
||||
/// </returns>
|
||||
/// <throws> ReaderException Any errors which occurred </throws>
|
||||
public Result decodeWithState(BinaryBitmap image)
|
||||
{
|
||||
// Make sure to set up the default state so we don't crash
|
||||
if (readers == null)
|
||||
{
|
||||
Hints = null;
|
||||
}
|
||||
return decodeInternal(image);
|
||||
}
|
||||
|
||||
/// <summary> This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
|
||||
/// to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
|
||||
/// is important for performance in continuous scan clients.
|
||||
///
|
||||
/// </summary>
|
||||
public IDictionary<DecodeHintType, object> Hints
|
||||
{
|
||||
set
|
||||
{
|
||||
hints = value;
|
||||
|
||||
var tryHarder = value != null && value.ContainsKey(DecodeHintType.TRY_HARDER);
|
||||
var formats = value == null || !value.ContainsKey(DecodeHintType.POSSIBLE_FORMATS) ? null : (IList<BarcodeFormat>)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<Reader>();
|
||||
|
||||
// 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<Reader>();
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// resets all specific readers
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
101
Others/zxing.core/zxing.core/MultiFormatWriter.cs
Normal file
101
Others/zxing.core/zxing.core/MultiFormatWriter.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary> This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat
|
||||
/// requested and encodes the barcode with the supplied contents.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public sealed class MultiFormatWriter : Writer
|
||||
{
|
||||
private static readonly IDictionary<BarcodeFormat, Func<Writer>> formatMap;
|
||||
|
||||
static MultiFormatWriter()
|
||||
{
|
||||
formatMap = new Dictionary<BarcodeFormat, Func<Writer>>
|
||||
{
|
||||
{BarcodeFormat.EAN_8, () => new EAN8Writer()},
|
||||
{BarcodeFormat.UPC_E, () => new UPCEWriter()},
|
||||
{BarcodeFormat.EAN_13, () => new EAN13Writer()},
|
||||
{BarcodeFormat.UPC_A, () => new UPCAWriter()},
|
||||
{BarcodeFormat.QR_CODE, () => new QRCodeWriter()},
|
||||
{BarcodeFormat.CODE_39, () => new Code39Writer()},
|
||||
{BarcodeFormat.CODE_93, () => new Code93Writer()},
|
||||
{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()},
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of supported writers.
|
||||
/// </summary>
|
||||
public static ICollection<BarcodeFormat> SupportedWriters
|
||||
{
|
||||
get { return formatMap.Keys; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// encode the given data
|
||||
/// </summary>
|
||||
/// <param name="contents"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <returns></returns>
|
||||
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
|
||||
{
|
||||
return encode(contents, format, width, height, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// encode the given data
|
||||
/// </summary>
|
||||
/// <param name="contents"></param>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="hints"></param>
|
||||
/// <returns></returns>
|
||||
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> hints)
|
||||
{
|
||||
if (!formatMap.ContainsKey(format))
|
||||
throw new ArgumentException("No encoder available for format " + format);
|
||||
|
||||
return formatMap[format]().encode(contents, format, width, height, hints);
|
||||
}
|
||||
}
|
||||
}
|
||||
267
Others/zxing.core/zxing.core/PlanarYUVLuminanceSource.cs
Normal file
267
Others/zxing.core/zxing.core/PlanarYUVLuminanceSource.cs
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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)
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlanarYUVLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="yuvData">The yuv data.</param>
|
||||
/// <param name="dataWidth">Width of the data.</param>
|
||||
/// <param name="dataHeight">Height of the data.</param>
|
||||
/// <param name="left">The left.</param>
|
||||
/// <param name="top">The top.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="reverseHoriz">if set to <c>true</c> [reverse horiz].</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlanarYUVLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="luminances">The luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
private PlanarYUVLuminanceSource(byte[] luminances, int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
yuvData = luminances;
|
||||
this.luminances = luminances;
|
||||
dataWidth = width;
|
||||
dataHeight = height;
|
||||
left = 0;
|
||||
top = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches one row of luminance data from the underlying platform's bitmap. Values range from
|
||||
/// 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
|
||||
/// to bitwise and with 0xff for each value. It is preferable for implementations of this method
|
||||
/// to only fetch this row rather than the whole image, since no 2D Readers may be installed and
|
||||
/// getMatrix() may never be called.
|
||||
/// </summary>
|
||||
/// <param name="y">The row to fetch, 0 <= y < Height.</param>
|
||||
/// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
|
||||
/// Always use the returned object, and ignore the .length of the array.</param>
|
||||
/// <returns>
|
||||
/// An array containing the luminance data.
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
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(yuvData, inputOffset, matrix, outputOffset, width);
|
||||
inputOffset += dataWidth;
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns> Whether this subclass supports cropping.</returns>
|
||||
override public bool CropSupported
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new object with cropped image data. Implementations may keep a reference to the
|
||||
/// original data rather than a copy. Only callable if CropSupported is true.
|
||||
/// </summary>
|
||||
/// <param name="left">The left coordinate, 0 <= left < Width.</param>
|
||||
/// <param name="top">The top coordinate, 0 <= top <= Height.</param>
|
||||
/// <param name="width">The width of the rectangle to crop.</param>
|
||||
/// <param name="height">The height of the rectangle to crop.</param>
|
||||
/// <returns>
|
||||
/// A cropped version of this object.
|
||||
/// </returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the cropped greyscale bitmap.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// width of image from {@link #renderThumbnail()}
|
||||
/// </summary>
|
||||
public int ThumbnailWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return Width / THUMBNAIL_SCALE_FACTOR;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// height of image from {@link #renderThumbnail()}
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// creates a new instance
|
||||
/// </summary>
|
||||
/// <param name="newLuminances"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <returns></returns>
|
||||
protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height)
|
||||
{
|
||||
return new PlanarYUVLuminanceSource(newLuminances, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
380
Others/zxing.core/zxing.core/RGBLuminanceSource.cs
Normal file
380
Others/zxing.core/zxing.core/RGBLuminanceSource.cs
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright 2012 ZXing.Net authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary>
|
||||
/// Luminance source class which support different formats of images.
|
||||
/// </summary>
|
||||
public partial class RGBLuminanceSource : BaseLuminanceSource
|
||||
{
|
||||
/// <summary>
|
||||
/// enumeration of supported bitmap format which the RGBLuminanceSource can process
|
||||
/// </summary>
|
||||
public enum BitmapFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// format of the byte[] isn't known. RGBLuminanceSource tries to determine the best possible value
|
||||
/// </summary>
|
||||
Unknown,
|
||||
/// <summary>
|
||||
/// grayscale array, the byte array is a luminance array with 1 byte per pixel
|
||||
/// </summary>
|
||||
Gray8,
|
||||
/// <summary>
|
||||
/// grayscale array, the byte array is a luminance array with 2 bytes per pixel
|
||||
/// </summary>
|
||||
Gray16,
|
||||
/// <summary>
|
||||
/// 3 bytes per pixel with the channels red, green and blue
|
||||
/// </summary>
|
||||
RGB24,
|
||||
/// <summary>
|
||||
/// 4 bytes per pixel with the channels red, green and blue
|
||||
/// </summary>
|
||||
RGB32,
|
||||
/// <summary>
|
||||
/// 4 bytes per pixel with the channels alpha, red, green and blue
|
||||
/// </summary>
|
||||
ARGB32,
|
||||
/// <summary>
|
||||
/// 3 bytes per pixel with the channels blue, green and red
|
||||
/// </summary>
|
||||
BGR24,
|
||||
/// <summary>
|
||||
/// 4 bytes per pixel with the channels blue, green and red
|
||||
/// </summary>
|
||||
BGR32,
|
||||
/// <summary>
|
||||
/// 4 bytes per pixel with the channels blue, green, red and alpha
|
||||
/// </summary>
|
||||
BGRA32,
|
||||
/// <summary>
|
||||
/// 2 bytes per pixel, 5 bit red, 6 bits green and 5 bits blue
|
||||
/// </summary>
|
||||
RGB565,
|
||||
/// <summary>
|
||||
/// 4 bytes per pixel with the channels red, green, blue and alpha
|
||||
/// </summary>
|
||||
RGBA32,
|
||||
/// <summary>
|
||||
/// 4 bytes for two pixels, UYVY formatted
|
||||
/// </summary>
|
||||
UYVY,
|
||||
/// <summary>
|
||||
/// 4 bytes for two pixels, YUYV formatted
|
||||
/// </summary>
|
||||
YUYV
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
protected RGBLuminanceSource(int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
|
||||
/// It supports a byte array with 3 bytes per pixel (RGB24).
|
||||
/// </summary>
|
||||
/// <param name="rgbRawBytes">The RGB raw bytes.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height)
|
||||
: this(rgbRawBytes, width, height, BitmapFormat.RGB24)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
|
||||
/// It supports a byte array with 1 byte per pixel (Gray8).
|
||||
/// That means the whole array consists of the luminance values (grayscale).
|
||||
/// </summary>
|
||||
/// <param name="luminanceArray">The luminance array.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="is8Bit">if set to <c>true</c> [is8 bit].</param>
|
||||
[Obsolete("Use RGBLuminanceSource(luminanceArray, width, height, BitmapFormat.Gray8)")]
|
||||
public RGBLuminanceSource(byte[] luminanceArray, int width, int height, bool is8Bit)
|
||||
: this(luminanceArray, width, height, BitmapFormat.Gray8)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
|
||||
/// It supports a byte array with 3 bytes per pixel (RGB24).
|
||||
/// </summary>
|
||||
/// <param name="rgbRawBytes">The RGB raw bytes.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="bitmapFormat">The bitmap format.</param>
|
||||
public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height, BitmapFormat bitmapFormat)
|
||||
: base(width, height)
|
||||
{
|
||||
CalculateLuminance(rgbRawBytes, bitmapFormat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should create a new luminance source with the right class type.
|
||||
/// The method is used in methods crop and rotate.
|
||||
/// </summary>
|
||||
/// <param name="newLuminances">The new luminances.</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns></returns>
|
||||
protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height)
|
||||
{
|
||||
return new RGBLuminanceSource(width, height) { luminances = newLuminances };
|
||||
}
|
||||
|
||||
private static BitmapFormat DetermineBitmapFormat(byte[] rgbRawBytes, int width, int height)
|
||||
{
|
||||
var square = width * height;
|
||||
var byteperpixel = rgbRawBytes.Length / square;
|
||||
|
||||
switch (byteperpixel)
|
||||
{
|
||||
case 1:
|
||||
return BitmapFormat.Gray8;
|
||||
case 2:
|
||||
return BitmapFormat.RGB565;
|
||||
case 3:
|
||||
return BitmapFormat.RGB24;
|
||||
case 4:
|
||||
return BitmapFormat.RGB32;
|
||||
default:
|
||||
throw new ArgumentException("The bitmap format could not be determined. Please specify the correct value.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculates the luminance values for the given byte array and bitmap format
|
||||
/// </summary>
|
||||
/// <param name="rgbRawBytes"></param>
|
||||
/// <param name="bitmapFormat"></param>
|
||||
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.Gray16:
|
||||
CalculateLuminanceGray16(rgbRawBytes);
|
||||
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;
|
||||
case BitmapFormat.UYVY:
|
||||
CalculateLuminanceUYVY(rgbRawBytes);
|
||||
break;
|
||||
case BitmapFormat.YUYV:
|
||||
CalculateLuminanceYUYV(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));
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLuminanceUYVY(byte[] uyvyRawBytes)
|
||||
{
|
||||
// start by 1, jump over first U byte
|
||||
for (int uyvyIndex = 1, luminanceIndex = 0; uyvyIndex < uyvyRawBytes.Length - 3 && luminanceIndex < luminances.Length;)
|
||||
{
|
||||
byte y1 = uyvyRawBytes[uyvyIndex];
|
||||
uyvyIndex += 2; // jump from 1 to 3 (from Y1 over to Y2)
|
||||
byte y2 = uyvyRawBytes[uyvyIndex];
|
||||
uyvyIndex += 2; // jump from 3 to 5
|
||||
|
||||
luminances[luminanceIndex++] = y1;
|
||||
luminances[luminanceIndex++] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLuminanceYUYV(byte[] yuyvRawBytes)
|
||||
{
|
||||
// start by 0 not by 1 like UYUV
|
||||
for (int yuyvIndex = 0, luminanceIndex = 0; yuyvIndex < yuyvRawBytes.Length - 3 && luminanceIndex < luminances.Length;)
|
||||
{
|
||||
byte y1 = yuyvRawBytes[yuyvIndex];
|
||||
yuyvIndex += 2; // jump from 0 to 2 (from Y1 over over to Y2)
|
||||
byte y2 = yuyvRawBytes[yuyvIndex];
|
||||
yuyvIndex += 2; // jump from 2 to 4
|
||||
|
||||
luminances[luminanceIndex++] = y1;
|
||||
luminances[luminanceIndex++] = y2;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateLuminanceGray16(byte[] gray16RawBytes)
|
||||
{
|
||||
for (int grayIndex = 0, luminanceIndex = 0; grayIndex < gray16RawBytes.Length && luminanceIndex < luminances.Length; grayIndex += 2, luminanceIndex++)
|
||||
{
|
||||
byte gray8 = gray16RawBytes[grayIndex];
|
||||
|
||||
luminances[luminanceIndex] = gray8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
Others/zxing.core/zxing.core/Reader.cs
Normal file
59
Others/zxing.core/zxing.core/Reader.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementations of this interface can decode an image of a barcode in some format into
|
||||
/// the String it encodes. For example, <see cref="ZXing.QrCode.QRCodeReader" /> can
|
||||
/// decode a QR code. The decoder may optionally receive hints from the caller which may help
|
||||
/// it decode more quickly or accurately.
|
||||
///
|
||||
/// See <see cref="MultiFormatReader" />, which attempts to determine what barcode
|
||||
/// format is present within the image as well, and then decodes it accordingly.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
public interface Reader
|
||||
{
|
||||
/// <summary>
|
||||
/// Locates and decodes a barcode in some format within an image.
|
||||
/// </summary>
|
||||
/// <param name="image">image of barcode to decode</param>
|
||||
/// <returns>String which the barcode encodes</returns>
|
||||
Result decode(BinaryBitmap image);
|
||||
|
||||
/// <summary> Locates and decodes a barcode in some format within an image. This method also accepts
|
||||
/// hints, each possibly associated to some data, which may help the implementation decode.
|
||||
/// </summary>
|
||||
/// <param name="image">image of barcode to decode</param>
|
||||
/// <param name="hints">passed as a <see cref="IDictionary{TKey, TValue}" /> from <see cref="DecodeHintType" />
|
||||
/// to arbitrary data. The
|
||||
/// meaning of the data depends upon the hint type. The implementation may or may not do
|
||||
/// anything with these hints.
|
||||
/// </param>
|
||||
/// <returns>String which the barcode encodes</returns>
|
||||
Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints);
|
||||
|
||||
/// <summary>
|
||||
/// Resets any internal state the implementation has after a decode, to prepare it
|
||||
/// for reuse.
|
||||
/// </summary>
|
||||
void reset();
|
||||
}
|
||||
}
|
||||
64
Others/zxing.core/zxing.core/ReaderException.cs
Normal file
64
Others/zxing.core/zxing.core/ReaderException.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// The general exception class throw when something goes wrong during decoding of a barcode.
|
||||
/// This includes, but is not limited to, failing checksums / error correction algorithms, being
|
||||
/// unable to locate finder timing patterns, and so on.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
[Serializable]
|
||||
public class ReaderException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReaderException"/> class.
|
||||
/// </summary>
|
||||
public ReaderException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReaderException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public ReaderException(String message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReaderException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="innerException">The inner exception.</param>
|
||||
public ReaderException(Exception innerException)
|
||||
: base(innerException.Message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReaderException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="innerException">The inner exception.</param>
|
||||
/// <param name="message"></param>
|
||||
public ReaderException(String message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
198
Others/zxing.core/zxing.core/Result.cs
Normal file
198
Others/zxing.core/zxing.core/Result.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates the result of decoding a barcode within an image.
|
||||
/// </summary>
|
||||
public sealed class Result
|
||||
{
|
||||
/// <returns>raw text encoded by the barcode, if applicable, otherwise <code>null</code></returns>
|
||||
public String Text { get; private set; }
|
||||
|
||||
/// <returns>raw bytes encoded by the barcode, if applicable, otherwise <code>null</code></returns>
|
||||
public byte[] RawBytes { get; private set; }
|
||||
|
||||
/// <returns>
|
||||
/// points related to the barcode in the image. These are typically points
|
||||
/// identifying finder patterns or the corners of the barcode. The exact meaning is
|
||||
/// specific to the type of barcode that was decoded.
|
||||
/// </returns>
|
||||
public ResultPoint[] ResultPoints { get; private set; }
|
||||
|
||||
/// <returns>{@link BarcodeFormat} representing the format of the barcode that was decoded</returns>
|
||||
public BarcodeFormat BarcodeFormat { get; private set; }
|
||||
|
||||
/// <returns>
|
||||
/// {@link Hashtable} mapping {@link ResultMetadataType} keys to values. May be
|
||||
/// <code>null</code>. This contains optional metadata about what was detected about the barcode,
|
||||
/// like orientation.
|
||||
/// </returns>
|
||||
public IDictionary<ResultMetadataType, object> ResultMetadata { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the timestamp.
|
||||
/// </summary>
|
||||
public long Timestamp { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// how many bits of <see cref="RawBytes"/> are valid; typically 8 times its length
|
||||
/// </summary>
|
||||
public int NumBits { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Result"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="rawBytes">The raw bytes.</param>
|
||||
/// <param name="resultPoints">The result points.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
public Result(String text,
|
||||
byte[] rawBytes,
|
||||
ResultPoint[] resultPoints,
|
||||
BarcodeFormat format)
|
||||
: this(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.Length, resultPoints, format, DateTime.Now.Ticks)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Result"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="rawBytes">The raw bytes.</param>
|
||||
/// <param name="numBits"></param>
|
||||
/// <param name="resultPoints">The result points.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
public Result(String text,
|
||||
byte[] rawBytes,
|
||||
int numBits,
|
||||
ResultPoint[] resultPoints,
|
||||
BarcodeFormat format)
|
||||
: this(text, rawBytes, numBits, resultPoints, format, DateTime.Now.Ticks)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Result"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="rawBytes">The raw bytes.</param>
|
||||
/// <param name="resultPoints">The result points.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <param name="timestamp">The timestamp.</param>
|
||||
public Result(String text, byte[] rawBytes, ResultPoint[] resultPoints, BarcodeFormat format, long timestamp)
|
||||
: this(text, rawBytes, rawBytes == null ? 0 : 8 * rawBytes.Length, resultPoints, format, timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Result"/> class.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <param name="rawBytes">The raw bytes.</param>
|
||||
/// <param name="numBits"></param>
|
||||
/// <param name="resultPoints">The result points.</param>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <param name="timestamp">The timestamp.</param>
|
||||
public Result(String text, byte[] rawBytes, int numBits, ResultPoint[] resultPoints, BarcodeFormat format, long timestamp)
|
||||
{
|
||||
if (text == null && rawBytes == null)
|
||||
{
|
||||
throw new ArgumentException("Text and bytes are null");
|
||||
}
|
||||
Text = text;
|
||||
RawBytes = rawBytes;
|
||||
NumBits = numBits;
|
||||
ResultPoints = resultPoints;
|
||||
BarcodeFormat = format;
|
||||
ResultMetadata = null;
|
||||
Timestamp = timestamp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds one metadata to the result
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public void putMetadata(ResultMetadataType type, Object value)
|
||||
{
|
||||
if (ResultMetadata == null)
|
||||
{
|
||||
ResultMetadata = new Dictionary<ResultMetadataType, object>();
|
||||
}
|
||||
ResultMetadata[type] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a list of metadata to the result
|
||||
/// </summary>
|
||||
/// <param name="metadata">The metadata.</param>
|
||||
public void putAllMetadata(IDictionary<ResultMetadataType, object> metadata)
|
||||
{
|
||||
if (metadata != null)
|
||||
{
|
||||
if (ResultMetadata == null)
|
||||
{
|
||||
ResultMetadata = metadata;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var entry in metadata)
|
||||
ResultMetadata[entry.Key] = entry.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the result points.
|
||||
/// </summary>
|
||||
/// <param name="newPoints">The new points.</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> that represents this instance.
|
||||
/// </returns>
|
||||
public override String ToString()
|
||||
{
|
||||
if (Text == null)
|
||||
{
|
||||
return "[" + RawBytes.Length + " bytes]";
|
||||
}
|
||||
return Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
102
Others/zxing.core/zxing.core/ResultMetadataType.cs
Normal file
102
Others/zxing.core/zxing.core/ResultMetadataType.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents some type of metadata about the result of the decoding that the decoder
|
||||
/// wishes to communicate back to the caller.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public enum ResultMetadataType
|
||||
{
|
||||
/// <summary>
|
||||
/// Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.
|
||||
/// </summary>
|
||||
OTHER,
|
||||
|
||||
/// <summary>
|
||||
/// Denotes the likely approximate orientation of the barcode in the image. This value
|
||||
/// is given as degrees rotated clockwise from the normal, upright orientation.
|
||||
/// For example a 1D barcode which was found by reading top-to-bottom would be
|
||||
/// said to have orientation "90". This key maps to an {@link Integer} whose
|
||||
/// value is in the range [0,360).
|
||||
/// </summary>
|
||||
ORIENTATION,
|
||||
|
||||
/// <summary>
|
||||
/// <p>2D barcode formats typically encode text, but allow for a sort of 'byte mode'
|
||||
/// which is sometimes used to encode binary data. While {@link Result} makes available
|
||||
/// the complete raw bytes in the barcode for these formats, it does not offer the bytes
|
||||
/// from the byte segments alone.</p>
|
||||
/// <p>This maps to a {@link java.util.List} of byte arrays corresponding to the
|
||||
/// raw bytes in the byte segments in the barcode, in order.</p>
|
||||
/// </summary>
|
||||
BYTE_SEGMENTS,
|
||||
|
||||
/// <summary>
|
||||
/// Error correction level used, if applicable. The value type depends on the
|
||||
/// format, but is typically a String.
|
||||
/// </summary>
|
||||
ERROR_CORRECTION_LEVEL,
|
||||
|
||||
/// <summary>
|
||||
/// For some periodicals, indicates the issue number as an {@link Integer}.
|
||||
/// </summary>
|
||||
ISSUE_NUMBER,
|
||||
|
||||
/// <summary>
|
||||
/// For some products, indicates the suggested retail price in the barcode as a
|
||||
/// formatted {@link String}.
|
||||
/// </summary>
|
||||
SUGGESTED_PRICE,
|
||||
|
||||
/// <summary>
|
||||
/// 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".
|
||||
/// </summary>
|
||||
POSSIBLE_COUNTRY,
|
||||
|
||||
/// <summary>
|
||||
/// For some products, the extension text
|
||||
/// </summary>
|
||||
UPC_EAN_EXTENSION,
|
||||
|
||||
/// <summary>
|
||||
/// If the code format supports structured append and
|
||||
/// the current scanned code is part of one then the
|
||||
/// sequence number is given with it.
|
||||
/// </summary>
|
||||
STRUCTURED_APPEND_SEQUENCE,
|
||||
|
||||
/// <summary>
|
||||
/// If the code format supports structured append and
|
||||
/// the current scanned code is part of one then the
|
||||
/// parity is given with it.
|
||||
/// </summary>
|
||||
STRUCTURED_APPEND_PARITY,
|
||||
|
||||
/// <summary>
|
||||
/// PDF417-specific metadata
|
||||
/// </summary>
|
||||
PDF417_EXTRA_METADATA,
|
||||
|
||||
/// <summary>
|
||||
/// Aztec-specific metadata
|
||||
/// </summary>
|
||||
AZTEC_EXTRA_METADATA
|
||||
}
|
||||
}
|
||||
196
Others/zxing.core/zxing.core/ResultPoint.cs
Normal file
196
Others/zxing.core/zxing.core/ResultPoint.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public class ResultPoint
|
||||
{
|
||||
private readonly float x;
|
||||
private readonly float y;
|
||||
private readonly byte[] bytesX;
|
||||
private readonly byte[] bytesY;
|
||||
private String toString;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ResultPoint"/> class.
|
||||
/// </summary>
|
||||
public ResultPoint()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ResultPoint"/> class.
|
||||
/// </summary>
|
||||
/// <param name="x">The x.</param>
|
||||
/// <param name="y">The y.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the X.
|
||||
/// </summary>
|
||||
virtual public float X
|
||||
{
|
||||
get
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Y.
|
||||
/// </summary>
|
||||
virtual public float Y
|
||||
{
|
||||
get
|
||||
{
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
|
||||
/// </summary>
|
||||
/// <param name="other">The <see cref="System.Object"/> to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool Equals(Object other)
|
||||
{
|
||||
var otherPoint = other as ResultPoint;
|
||||
if (otherPoint == null)
|
||||
return false;
|
||||
return x == otherPoint.x && y == otherPoint.y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
|
||||
/// </returns>
|
||||
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];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String"/> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String"/> that represents this instance.
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="patterns">array of three <see cref="ResultPoint" /> to order</param>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// calculates the distance between two points
|
||||
/// </summary>
|
||||
/// <param name="pattern1">first pattern</param>
|
||||
/// <param name="pattern2">second pattern</param>
|
||||
/// <returns>
|
||||
/// distance between two points
|
||||
/// </returns>
|
||||
public static float distance(ResultPoint pattern1, ResultPoint pattern2)
|
||||
{
|
||||
return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the z component of the cross product between vectors BC and BA.
|
||||
/// </summary>
|
||||
private static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC)
|
||||
{
|
||||
float bX = pointB.x;
|
||||
float bY = pointB.y;
|
||||
return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Others/zxing.core/zxing.core/ResultPointCallback.cs
Normal file
26
Others/zxing.core/zxing.core/ResultPointCallback.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary> Callback which is invoked when a possible result point (significant
|
||||
/// point in the barcode image such as a corner) is found.
|
||||
///
|
||||
/// </summary>
|
||||
/// <seealso cref="DecodeHintType.NEED_RESULT_POINT_CALLBACK">
|
||||
/// </seealso>
|
||||
public delegate void ResultPointCallback(ResultPoint point);
|
||||
}
|
||||
185
Others/zxing.core/zxing.core/SupportClass.cs
Normal file
185
Others/zxing.core/zxing.core/SupportClass.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
//
|
||||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains conversion support elements such as classes, interfaces and static methods.
|
||||
/// </summary>
|
||||
public static class SupportClass
|
||||
{
|
||||
/*******************************/
|
||||
/// <summary>
|
||||
/// Copies an array of chars obtained from a String into a specified array of chars
|
||||
/// </summary>
|
||||
/// <param name="sourceString">The String to get the chars from</param>
|
||||
/// <param name="sourceStart">Position of the String to start getting the chars</param>
|
||||
/// <param name="sourceEnd">Position of the String to end getting the chars</param>
|
||||
/// <param name="destinationArray">Array to return the chars</param>
|
||||
/// <param name="destinationStart">Position of the destination array of chars to start storing the chars</param>
|
||||
/// <returns>An array of chars</returns>
|
||||
public static void GetCharsFromString(System.String sourceString, int sourceStart, int sourceEnd, char[] destinationArray, int destinationStart)
|
||||
{
|
||||
int sourceCounter = sourceStart;
|
||||
int destinationCounter = destinationStart;
|
||||
while (sourceCounter < sourceEnd)
|
||||
{
|
||||
destinationArray[destinationCounter] = (char)sourceString[sourceCounter];
|
||||
sourceCounter++;
|
||||
destinationCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/// <summary>
|
||||
/// Sets the capacity for the specified List
|
||||
/// </summary>
|
||||
/// <param name="vector">The List which capacity will be set</param>
|
||||
/// <param name="newCapacity">The new capacity value</param>
|
||||
public static void SetCapacity<T>(System.Collections.Generic.IList<T> vector, int newCapacity) where T : new()
|
||||
{
|
||||
while (newCapacity > vector.Count)
|
||||
vector.Add(new T());
|
||||
while (newCapacity < vector.Count)
|
||||
vector.RemoveAt(vector.Count - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string-Collection to an array
|
||||
/// </summary>
|
||||
/// <param name="strings">The strings.</param>
|
||||
/// <returns></returns>
|
||||
public static String[] toStringArray(ICollection<string> strings)
|
||||
{
|
||||
var result = new String[strings.Count];
|
||||
strings.CopyTo(result, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Joins all elements to one string.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="separator">The separator.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
/// <returns></returns>
|
||||
public static string Join<T>(string separator, IEnumerable<T> 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the specified array.
|
||||
/// (can't use extension method because of .Net 2.0 support)
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="array">The array.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public static void Fill<T>(T[] array, T value)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the specified array.
|
||||
/// (can't use extension method because of .Net 2.0 support)
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="array">The array.</param>
|
||||
/// <param name="startIndex">The start index.</param>
|
||||
/// <param name="endIndex">The end index.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
public static void Fill<T>(T[] array, int startIndex, int endIndex, T value)
|
||||
{
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="n"></param>
|
||||
/// <returns></returns>
|
||||
public static int bitCount(int n)
|
||||
{
|
||||
int ret = 0;
|
||||
while (n != 0)
|
||||
{
|
||||
n &= (n - 1);
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Savely gets the value of a decoding hint
|
||||
/// if hints is null the default is returned
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="hints">The hints.</param>
|
||||
/// <param name="hintType">Type of the hint.</param>
|
||||
/// <param name="default">The @default.</param>
|
||||
/// <returns></returns>
|
||||
public static T GetValue<T>(IDictionary<DecodeHintType, object> 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Others/zxing.core/zxing.core/Writer.cs
Normal file
51
Others/zxing.core/zxing.core/Writer.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2008 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ZXing.Common;
|
||||
|
||||
namespace ZXing
|
||||
{
|
||||
/// <summary> The base class for all objects which encode/generate a barcode image.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> dswitkin@google.com (Daniel Switkin)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public interface Writer
|
||||
{
|
||||
/// <summary>
|
||||
/// Encode a barcode using the default settings.
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents to encode in the barcode</param>
|
||||
/// <param name="format">The barcode format to generate</param>
|
||||
/// <param name="width">The preferred width in pixels</param>
|
||||
/// <param name="height">The preferred height in pixels</param>
|
||||
/// <returns> The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)</returns>
|
||||
BitMatrix encode(System.String contents, BarcodeFormat format, int width, int height);
|
||||
|
||||
/// <summary> </summary>
|
||||
/// <param name="contents">The contents to encode in the barcode</param>
|
||||
/// <param name="format">The barcode format to generate</param>
|
||||
/// <param name="width">The preferred width in pixels</param>
|
||||
/// <param name="height">The preferred height in pixels</param>
|
||||
/// <param name="hints">Additional parameters to supply to the encoder</param>
|
||||
/// <returns> The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)</returns>
|
||||
BitMatrix encode(String contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> hints);
|
||||
}
|
||||
}
|
||||
55
Others/zxing.core/zxing.core/WriterException.cs
Normal file
55
Others/zxing.core/zxing.core/WriterException.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class which covers the range of exceptions which may occur when encoding a barcode using
|
||||
/// the Writer framework.
|
||||
/// </summary>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
[Serializable]
|
||||
public sealed class WriterException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WriterException"/> class.
|
||||
/// </summary>
|
||||
public WriterException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WriterException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public WriterException(String message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WriterException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="innerExc">The inner exc.</param>
|
||||
public WriterException(String message, Exception innerExc)
|
||||
: base(message, innerExc)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Others/zxing.core/zxing.core/aztec/AztecDetectorResult.cs
Normal file
63
Others/zxing.core/zxing.core/aztec/AztecDetectorResult.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Extends <see cref="DetectorResult" /> with more information specific to the Aztec format,
|
||||
/// like the number of layers and whether it's compact.
|
||||
/// </summary>
|
||||
public class AztecDetectorResult : DetectorResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this Aztec code is compact.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if compact; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool Compact { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the nb datablocks.
|
||||
/// </summary>
|
||||
public int NbDatablocks { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the nb layers.
|
||||
/// </summary>
|
||||
public int NbLayers { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AztecDetectorResult"/> class.
|
||||
/// </summary>
|
||||
/// <param name="bits">The bits.</param>
|
||||
/// <param name="points">The points.</param>
|
||||
/// <param name="compact">if set to <c>true</c> [compact].</param>
|
||||
/// <param name="nbDatablocks">The nb datablocks.</param>
|
||||
/// <param name="nbLayers">The nb layers.</param>
|
||||
public AztecDetectorResult(BitMatrix bits,
|
||||
ResultPoint[] points,
|
||||
bool compact,
|
||||
int nbDatablocks,
|
||||
int nbLayers)
|
||||
: base(bits, points)
|
||||
{
|
||||
Compact = compact;
|
||||
NbDatablocks = nbDatablocks;
|
||||
NbLayers = nbLayers;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
Others/zxing.core/zxing.core/aztec/AztecReader.cs
Normal file
123
Others/zxing.core/zxing.core/aztec/AztecReader.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// This implementation can detect and decode Aztec codes in an image.
|
||||
/// </summary>
|
||||
/// <author>David Olivier</author>
|
||||
public class AztecReader : Reader
|
||||
{
|
||||
/// <summary>
|
||||
/// Locates and decodes a barcode in some format within an image.
|
||||
/// </summary>
|
||||
/// <param name="image">image of barcode to decode</param>
|
||||
/// <returns>
|
||||
/// a String representing the content encoded by the Data Matrix code
|
||||
/// </returns>
|
||||
public Result decode(BinaryBitmap image)
|
||||
{
|
||||
return decode(image, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locates and decodes a Data Matrix code in an image.
|
||||
/// </summary>
|
||||
/// <param name="image">image of barcode to decode</param>
|
||||
/// <param name="hints">passed as a {@link java.util.Hashtable} from {@link com.google.zxing.DecodeHintType}
|
||||
/// to arbitrary data. The
|
||||
/// meaning of the data depends upon the hint type. The implementation may or may not do
|
||||
/// anything with these hints.</param>
|
||||
/// <returns>
|
||||
/// String which the barcode encodes
|
||||
/// </returns>
|
||||
public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> 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, decoderResult.NumBits, points, BarcodeFormat.AZTEC);
|
||||
|
||||
IList<byte[]> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets any internal state the implementation has after a decode, to prepare it
|
||||
/// for reuse.
|
||||
/// </summary>
|
||||
public void reset()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Others/zxing.core/zxing.core/aztec/AztecResultMetadata.cs
Normal file
53
Others/zxing.core/zxing.core/aztec/AztecResultMetadata.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Aztec result meta data.
|
||||
/// </summary>
|
||||
public sealed class AztecResultMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this Aztec code is compact.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if compact; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool Compact { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the nb datablocks.
|
||||
/// </summary>
|
||||
public int Datablocks { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the nb layers.
|
||||
/// </summary>
|
||||
public int Layers { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="compact"></param>
|
||||
/// <param name="datablocks"></param>
|
||||
/// <param name="layers"></param>
|
||||
public AztecResultMetadata(bool compact, int datablocks, int layers)
|
||||
{
|
||||
Compact = compact;
|
||||
Datablocks = datablocks;
|
||||
Layers = layers;
|
||||
}
|
||||
}
|
||||
}
|
||||
195
Others/zxing.core/zxing.core/aztec/AztecWriter.cs
Normal file
195
Others/zxing.core/zxing.core/aztec/AztecWriter.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders an Aztec code as a <see cref="BitMatrix" />
|
||||
/// </summary>
|
||||
public sealed class AztecWriter : Writer
|
||||
{
|
||||
public 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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode a barcode using the default settings.
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents to encode in the barcode</param>
|
||||
/// <param name="format">The barcode format to generate</param>
|
||||
/// <param name="width">The preferred width in pixels</param>
|
||||
/// <param name="height">The preferred height in pixels</param>
|
||||
/// <returns>
|
||||
/// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
|
||||
/// </returns>
|
||||
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
|
||||
{
|
||||
return encode(contents, format, width, height, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents to encode in the barcode</param>
|
||||
/// <param name="format">The barcode format to generate</param>
|
||||
/// <param name="width">The preferred width in pixels</param>
|
||||
/// <param name="height">The preferred height in pixels</param>
|
||||
/// <param name="hints">Additional parameters to supply to the encoder</param>
|
||||
/// <returns>
|
||||
/// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
|
||||
/// </returns>
|
||||
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> hints)
|
||||
{
|
||||
var charset = DEFAULT_CHARSET;
|
||||
if (hints != null)
|
||||
{
|
||||
if (hints.ContainsKey(EncodeHintType.CHARACTER_SET))
|
||||
{
|
||||
object charsetname = hints[EncodeHintType.CHARACTER_SET];
|
||||
if (charsetname != null)
|
||||
{
|
||||
charset = Encoding.GetEncoding(charsetname.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var byteContent = charset.GetBytes(contents);
|
||||
return encode(byteContent, format, width, height, hints);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="contents">The contents to encode in the barcode</param>
|
||||
/// <param name="format">The barcode format to generate</param>
|
||||
/// <param name="width">The preferred width in pixels</param>
|
||||
/// <param name="height">The preferred height in pixels</param>
|
||||
/// <param name="hints">Additional parameters to supply to the encoder</param>
|
||||
/// <returns>
|
||||
/// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
|
||||
/// </returns>
|
||||
public BitMatrix encode(byte[] contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> 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(byte[] contents, BarcodeFormat format, int width, int height, Encoding charset, int eccPercent, int layers)
|
||||
{
|
||||
// charset stays here for later use in ECI segment
|
||||
|
||||
if (format != BarcodeFormat.AZTEC)
|
||||
{
|
||||
throw new ArgumentException("Can only encode AZTEC code, but got " + format);
|
||||
}
|
||||
var aztec = Internal.Encoder.encode(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
538
Others/zxing.core/zxing.core/aztec/decoder/Decoder.cs
Normal file
538
Others/zxing.core/zxing.core/aztec/decoder/Decoder.cs
Normal file
@@ -0,0 +1,538 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// The main class which implements Aztec Code decoding -- as opposed to locating and extracting
|
||||
/// the Aztec Code from an image.
|
||||
/// </summary>
|
||||
/// <author>David Olivier</author>
|
||||
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",
|
||||
"\xB", "\f", "\r", "\x1B", "\x1C", "\x1D", "\x1E", "\x1F", "@", "\\", "^", "_",
|
||||
"`", "|", "~", "\x7F", "CTRL_LL", "CTRL_UL", "CTRL_PL", "CTRL_BS"
|
||||
};
|
||||
|
||||
private static readonly String[] PUNCT_TABLE =
|
||||
{
|
||||
"FLG(n)", "\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 Encoding DEFAULT_ENCODING = AztecWriter.DEFAULT_CHARSET;
|
||||
|
||||
private static readonly IDictionary<Table, String[]> codeTables = new Dictionary<Table, String[]>
|
||||
{
|
||||
{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<char, Table> codeTableMap = new Dictionary<char, Table>
|
||||
{
|
||||
{'U', Table.UPPER},
|
||||
{'L', Table.LOWER},
|
||||
{'M', Table.MIXED},
|
||||
{'P', Table.PUNCT},
|
||||
{'D', Table.DIGIT},
|
||||
{'B', Table.BINARY}
|
||||
};
|
||||
|
||||
private AztecDetectorResult ddata;
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified detector result.
|
||||
/// </summary>
|
||||
/// <param name="detectorResult">The detector result.</param>
|
||||
/// <returns></returns>
|
||||
public DecoderResult decode(AztecDetectorResult detectorResult)
|
||||
{
|
||||
ddata = detectorResult;
|
||||
var matrix = detectorResult.Bits;
|
||||
var rawbits = extractBits(matrix);
|
||||
if (rawbits == null)
|
||||
return null;
|
||||
|
||||
var correctedBits = correctBits(rawbits);
|
||||
if (correctedBits == null)
|
||||
return null;
|
||||
|
||||
var result = getEncodedData(correctedBits.correctBits);
|
||||
if (result == null)
|
||||
return null;
|
||||
|
||||
var rawBytes = convertBoolArrayToByteArray(correctedBits.correctBits);
|
||||
|
||||
var decoderResult = new DecoderResult(rawBytes, correctedBits.correctBits.Length, result, null, String.Format("{0}", correctedBits.ecLevel));
|
||||
return decoderResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is used for testing the high-level encoder
|
||||
/// </summary>
|
||||
/// <param name="correctedBits"></param>
|
||||
/// <returns></returns>
|
||||
public static String highLevelDecode(bool[] correctedBits)
|
||||
{
|
||||
return getEncodedData(correctedBits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the string encoded in the aztec code bits
|
||||
/// </summary>
|
||||
/// <param name="correctedBits">The corrected bits.</param>
|
||||
/// <returns>the decoded string</returns>
|
||||
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 index = 0;
|
||||
|
||||
|
||||
// Final decoded string result
|
||||
// (correctedBits-5) / 4 is an upper bound on the size (all-digit result)
|
||||
var result = new StringBuilder((correctedBits.Length - 5) / 4);
|
||||
|
||||
// Intermediary buffer of decoded bytes, which is decoded into a string and flushed
|
||||
// when character encoding changes (ECI) or input ends.
|
||||
using (var decodedBytes = new System.IO.MemoryStream())
|
||||
{
|
||||
var encoding = DEFAULT_ENCODING;
|
||||
|
||||
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);
|
||||
decodedBytes.WriteByte((byte)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 ("FLG(n)".Equals(str))
|
||||
{
|
||||
if (endIndex - index < 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int n = readCode(correctedBits, index, 3);
|
||||
index += 3;
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
result.Append((char)29); // translate FNC1 as ASCII 29
|
||||
break;
|
||||
case 7:
|
||||
throw new FormatException("FLG(7) is reserved and illegal");
|
||||
default:
|
||||
// flush bytes before changing character set
|
||||
if (decodedBytes.Length > 0)
|
||||
{
|
||||
var byteArray = decodedBytes.ToArray();
|
||||
result.Append(encoding.GetString(byteArray, 0, byteArray.Length));
|
||||
decodedBytes.SetLength(0);
|
||||
}
|
||||
|
||||
// ECI is decimal integer encoded as 1-6 codes in DIGIT mode
|
||||
int eci = 0;
|
||||
if (endIndex - index < 4 * n)
|
||||
{
|
||||
break;
|
||||
}
|
||||
while (n-- > 0)
|
||||
{
|
||||
int nextDigit = readCode(correctedBits, index, 4);
|
||||
index += 4;
|
||||
if (nextDigit < 2 || nextDigit > 11)
|
||||
{
|
||||
throw new FormatException("Not a decimal digit");
|
||||
}
|
||||
eci = eci * 10 + (nextDigit - 2);
|
||||
}
|
||||
CharacterSetECI charsetECI = CharacterSetECI.getCharacterSetECIByValue(eci);
|
||||
encoding = CharacterSetECI.getEncoding(charsetECI);
|
||||
break;
|
||||
}
|
||||
// Go back to whatever mode we had been in
|
||||
shiftTable = latchTable;
|
||||
strTable = codeTables[shiftTable];
|
||||
}
|
||||
else if (str.StartsWith("CTRL_"))
|
||||
{
|
||||
// Table changes
|
||||
// ISO/IEC 24778:2008 prescribes ending a shift sequence in the mode from which it was invoked.
|
||||
// That's including when that mode is a shift.
|
||||
// Our test case dlusbs.png for issue #642 exercises that.
|
||||
latchTable = shiftTable; // Latch the current mode, so as to return to Upper after U/S B/S
|
||||
shiftTable = getTable(str[5]);
|
||||
strTable = codeTables[shiftTable];
|
||||
if (str[6] == 'L')
|
||||
{
|
||||
latchTable = shiftTable;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Though stored as a table of strings for convenience, codes actually represent 1 or 2 *bytes*.
|
||||
#if (PORTABLE || NETSTANDARD1_0 || NETSTANDARD1_1)
|
||||
var b = Encoding.GetEncoding(StringUtils.PLATFORM_DEFAULT_ENCODING).GetBytes(str);
|
||||
#else
|
||||
|
||||
var b = Encoding.ASCII.GetBytes(str);
|
||||
#endif
|
||||
decodedBytes.Write(b, 0, b.Length);
|
||||
// Go back to whatever mode we had been in
|
||||
shiftTable = latchTable;
|
||||
strTable = codeTables[shiftTable];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (decodedBytes.Length > 0)
|
||||
{
|
||||
var byteArray = decodedBytes.ToArray();
|
||||
result.Append(encoding.GetString(byteArray, 0, byteArray.Length));
|
||||
}
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// gets the table corresponding to the char passed
|
||||
/// </summary>
|
||||
/// <param name="t">The t.</param>
|
||||
/// <returns></returns>
|
||||
private static Table getTable(char t)
|
||||
{
|
||||
if (!codeTableMap.ContainsKey(t))
|
||||
return codeTableMap['U'];
|
||||
return codeTableMap[t];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the character (or string) corresponding to the passed code in the given table
|
||||
/// </summary>
|
||||
/// <param name="table">the table used</param>
|
||||
/// <param name="code">the code of the character</param>
|
||||
/// <returns></returns>
|
||||
private static String getCharacter(String[] table, int code)
|
||||
{
|
||||
return table[code];
|
||||
}
|
||||
|
||||
internal sealed class CorrectedBitsResult
|
||||
{
|
||||
public bool[] correctBits;
|
||||
public int ecLevel;
|
||||
|
||||
public CorrectedBitsResult(bool[] correctBits, int ecLevel)
|
||||
{
|
||||
this.correctBits = correctBits;
|
||||
this.ecLevel = ecLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///Performs RS error correction on an array of bits.
|
||||
/// </summary>
|
||||
/// <param name="rawbits">The rawbits.</param>
|
||||
/// <returns>the corrected array</returns>
|
||||
private CorrectedBitsResult 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 new CorrectedBitsResult(correctedBits, 100 * (numCodewords - numDataCodewords) / numCodewords);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the array of bits from an Aztec Code matrix
|
||||
/// </summary>
|
||||
/// <param name="matrix">The matrix.</param>
|
||||
/// <returns>the array of bits</returns>
|
||||
private bool[] extractBits(BitMatrix matrix)
|
||||
{
|
||||
bool compact = ddata.Compact;
|
||||
int layers = ddata.NbLayers;
|
||||
int baseMatrixSize = (compact ? 11 : 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 = (layers - i) * 4 + (compact ? 9 : 12);
|
||||
// The top-left most point of this layer is <low, low> (not including alignment lines)
|
||||
int low = i * 2;
|
||||
// The bottom-right most point of this layer is <high, high> (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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a code of given length and at given index in an array of bits
|
||||
/// </summary>
|
||||
/// <param name="rawbits">The rawbits.</param>
|
||||
/// <param name="startIndex">The start index.</param>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <returns></returns>
|
||||
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 |= 1;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a code of length 8 in an array of bits, padding with zeros
|
||||
/// </summary>
|
||||
/// <param name="rawbits"></param>
|
||||
/// <param name="startIndex"></param>
|
||||
/// <returns></returns>
|
||||
private static byte readByte(bool[] rawbits, int startIndex)
|
||||
{
|
||||
int n = rawbits.Length - startIndex;
|
||||
if (n >= 8)
|
||||
{
|
||||
return (byte)readCode(rawbits, startIndex, 8);
|
||||
}
|
||||
return (byte)(readCode(rawbits, startIndex, n) << (8 - n));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Packs a bit array into bytes, most significant bit first
|
||||
/// </summary>
|
||||
/// <param name="boolArr"></param>
|
||||
/// <returns></returns>
|
||||
internal static byte[] convertBoolArrayToByteArray(bool[] boolArr)
|
||||
{
|
||||
byte[] byteArr = new byte[(boolArr.Length + 7) / 8];
|
||||
for (int i = 0; i < byteArr.Length; i++)
|
||||
{
|
||||
byteArr[i] = readByte(boolArr, 8 * i);
|
||||
}
|
||||
return byteArr;
|
||||
}
|
||||
|
||||
private static int totalBitsInLayer(int layers, bool compact)
|
||||
{
|
||||
return ((compact ? 88 : 112) + 16 * layers) * layers;
|
||||
}
|
||||
}
|
||||
}
|
||||
691
Others/zxing.core/zxing.core/aztec/detector/Detector.cs
Normal file
691
Others/zxing.core/zxing.core/aztec/detector/Detector.cs
Normal file
@@ -0,0 +1,691 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates logic that can detect an Aztec Code in an image, even if the Aztec Code
|
||||
/// is rotated or skewed, or partially obscured.
|
||||
/// </summary>
|
||||
/// <author>David Olivier</author>
|
||||
public sealed class Detector
|
||||
{
|
||||
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 readonly BitMatrix image;
|
||||
|
||||
private bool compact;
|
||||
private int nbLayers;
|
||||
private int nbDataBlocks;
|
||||
private int nbCenterLayers;
|
||||
private int shift;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Detector"/> class.
|
||||
/// </summary>
|
||||
/// <param name="image">The image.</param>
|
||||
public Detector(BitMatrix image)
|
||||
{
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects an Aztec Code in an image.
|
||||
/// </summary>
|
||||
public AztecDetectorResult detect()
|
||||
{
|
||||
return detect(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects an Aztec Code in an image.
|
||||
/// </summary>
|
||||
/// <param name="isMirror">if true, image is a mirror-image of original.</param>
|
||||
/// <returns>
|
||||
/// encapsulating results of detecting an Aztec Code
|
||||
/// </returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the number of data layers and data blocks from the layer around the bull's eye
|
||||
/// </summary>
|
||||
/// <param name="bullsEyeCorners">bullEyeCornerPoints the array of bull's eye corners</param>
|
||||
/// <returns></returns>
|
||||
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 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Corrects the parameter bits using Reed-Solomon algorithm
|
||||
/// </summary>
|
||||
/// <param name="parameterData">paremeter bits</param>
|
||||
/// <param name="compact">compact true if this is a compact Aztec code</param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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]
|
||||
/// </summary>
|
||||
/// <param name="pCenter">Center point</param>
|
||||
/// <returns>The corners of the bull-eye</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a candidate center point of an Aztec code from an image
|
||||
/// </summary>
|
||||
/// <returns>the center point</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Aztec code corners from the bull's eye corners and the parameters.
|
||||
/// </summary>
|
||||
/// <param name="bullsEyeCorners">the array of bull's eye corners</param>
|
||||
/// <returns>the array of aztec code corners</returns>
|
||||
private ResultPoint[] getMatrixCornerPoints(ResultPoint[] bullsEyeCorners)
|
||||
{
|
||||
return expandSquare(bullsEyeCorners, 2 * nbCenterLayers, getDimension());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="image">The image.</param>
|
||||
/// <param name="topLeft">The top left.</param>
|
||||
/// <param name="bottomLeft">The bottom left.</param>
|
||||
/// <param name="bottomRight">The bottom right.</param>
|
||||
/// <param name="topRight">The top right.</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Samples a line
|
||||
/// </summary>
|
||||
/// <param name="p1">start point (inclusive)</param>
|
||||
/// <param name="p2">end point (exclusive)</param>
|
||||
/// <param name="size">number of bits</param>
|
||||
/// <returns> the array of bits as an int (first bit is high-order bit of result)</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is white or black rectangle] [the specified p1].
|
||||
/// </summary>
|
||||
/// <param name="p1">The p1.</param>
|
||||
/// <param name="p2">The p2.</param>
|
||||
/// <param name="p3">The p3.</param>
|
||||
/// <param name="p4">The p4.</param>
|
||||
/// <returns>true if the border of the rectangle passed in parameter is compound of white points only
|
||||
/// or black points only</returns>
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color of a segment
|
||||
/// </summary>
|
||||
/// <param name="p1">The p1.</param>
|
||||
/// <param name="p2">The p2.</param>
|
||||
/// <returns>1 if segment more than 90% black, -1 if segment is more than 90% white, 0 else</returns>
|
||||
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];
|
||||
|
||||
int iMax = (int)Math.Ceiling(d);
|
||||
for (int i = 0; i < iMax; 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the coordinate of the first point with a different color in the given direction
|
||||
/// </summary>
|
||||
/// <param name="init">The init.</param>
|
||||
/// <param name="color">if set to <c>true</c> [color].</param>
|
||||
/// <param name="dx">The dx.</param>
|
||||
/// <param name="dy">The dy.</param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expand the square represented by the corner points by pushing out equally in all directions
|
||||
/// </summary>
|
||||
/// <param name="cornerPoints">the corners of the square, which has the bull's eye at its center</param>
|
||||
/// <param name="oldSide">the original length of the side of the square in the target bit matrix</param>
|
||||
/// <param name="newSide">the new length of the size of the square in the target bit matrix</param>
|
||||
/// <returns>the corners of the expanded square</returns>
|
||||
private static ResultPoint[] expandSquare(ResultPoint[] cornerPoints, int oldSide, int newSide)
|
||||
{
|
||||
float ratio = newSide / (2.0f * 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 + '>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
52
Others/zxing.core/zxing.core/aztec/encoder/AztecCode.cs
Normal file
52
Others/zxing.core/zxing.core/aztec/encoder/AztecCode.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Aztec 2D code representation
|
||||
/// </summary>
|
||||
/// <author>Rustam Abdullaev</author>
|
||||
public sealed class AztecCode
|
||||
{
|
||||
/// <summary>
|
||||
/// Compact or full symbol indicator
|
||||
/// </summary>
|
||||
public bool isCompact { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size in pixels (width and height)
|
||||
/// </summary>
|
||||
public int Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of levels
|
||||
/// </summary>
|
||||
public int Layers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of data codewords
|
||||
/// </summary>
|
||||
public int CodeWords { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The symbol image
|
||||
/// </summary>
|
||||
public BitMatrix Matrix { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.ComponentModel;
|
||||
|
||||
using ZXing.Common;
|
||||
|
||||
namespace ZXing.Aztec
|
||||
{
|
||||
/// <summary>
|
||||
/// The class holds the available options for the <see cref="AztecWriter" />
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class AztecEncodingOptions : EncodingOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Representing the minimal percentage of error correction words.
|
||||
/// Note: an Aztec symbol should have a minimum of 25% EC words.
|
||||
/// </summary>
|
||||
#if !NETSTANDARD && !NETFX_CORE && !WindowsCE && !SILVERLIGHT && !PORTABLE && !UNITY
|
||||
[CategoryAttribute("Standard"), DescriptionAttribute("The minimal percentage of error correction words (> 25%).")]
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
#if !NETSTANDARD && !NETFX_CORE && !WindowsCE && !SILVERLIGHT && !PORTABLE && !UNITY
|
||||
[CategoryAttribute("Standard"), DescriptionAttribute("The required number of layers for an Aztec code" +
|
||||
" -1 to -4 specify a compact code, 0 indicates to use the minimum number of layers and" +
|
||||
" 1 to 32 specify a normal (non-compact) Aztec code.")]
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what character encoding to use where applicable (type <see cref="String"/>)
|
||||
/// </summary>
|
||||
#if !NETSTANDARD && !NETFX_CORE && !WindowsCE && !SILVERLIGHT && !PORTABLE && !UNITY
|
||||
[CategoryAttribute("Standard"), DescriptionAttribute("Specifies what character encoding to use where applicable.")]
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// represents a token for a binary shift
|
||||
/// </summary>
|
||||
public sealed class BinaryShiftToken : Token
|
||||
{
|
||||
private readonly short binaryShiftStart;
|
||||
private readonly short binaryShiftByteCount;
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="previous"></param>
|
||||
/// <param name="binaryShiftStart"></param>
|
||||
/// <param name="binaryShiftByteCount"></param>
|
||||
public BinaryShiftToken(Token previous,
|
||||
int binaryShiftStart,
|
||||
int binaryShiftByteCount)
|
||||
: base(previous)
|
||||
{
|
||||
this.binaryShiftStart = (short)binaryShiftStart;
|
||||
this.binaryShiftByteCount = (short)binaryShiftByteCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// appends the byte array to the BitArray
|
||||
/// </summary>
|
||||
/// <param name="bitArray"></param>
|
||||
/// <param name="text"></param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// string representation
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return "<" + binaryShiftStart + "::" + (binaryShiftStart + binaryShiftByteCount - 1) + '>';
|
||||
}
|
||||
}
|
||||
}
|
||||
430
Others/zxing.core/zxing.core/aztec/encoder/Encoder.cs
Normal file
430
Others/zxing.core/zxing.core/aztec/encoder/Encoder.cs
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates Aztec 2D barcodes.
|
||||
/// </summary>
|
||||
/// <author>Rustam Abdullaev</author>
|
||||
public static class Encoder
|
||||
{
|
||||
/// <summary>
|
||||
/// default EC percent 33
|
||||
/// </summary>
|
||||
public const int DEFAULT_EC_PERCENT = 33; // default minimal percentage of error check words
|
||||
/// <summary>
|
||||
/// default layers 0
|
||||
/// </summary>
|
||||
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
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the given binary content as an Aztec symbol
|
||||
/// </summary>
|
||||
/// <param name="data">input data string</param>
|
||||
/// <returns>Aztec symbol matrix with metadata</returns>
|
||||
|
||||
public static AztecCode encode(byte[] data)
|
||||
{
|
||||
return encode(data, DEFAULT_EC_PERCENT, DEFAULT_AZTEC_LAYERS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the given binary content as an Aztec symbol
|
||||
/// </summary>
|
||||
/// <param name="data">input data string</param>
|
||||
/// <param name="minECCPercent">minimal percentage of error check words (According to ISO/IEC 24778:2008,
|
||||
/// a minimum of 23% + 3 words is recommended)</param>
|
||||
/// <param name="userSpecifiedLayers">if non-zero, a user-specified value for the number of layers</param>
|
||||
/// <returns>
|
||||
/// Aztec symbol matrix with metadata
|
||||
/// </returns>
|
||||
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 (stuffedBits == null || wordSize != WORD_SIZE[layers])
|
||||
{
|
||||
wordSize = WORD_SIZE[layers];
|
||||
stuffedBits = stuffBits(bits, wordSize);
|
||||
}
|
||||
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
|
||||
int baseMatrixSize = (compact ? 11 : 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 = (layers - i) * 4 + (compact ? 9 : 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:
|
||||
throw new ArgumentException("Unsupported word size " + wordSize);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
383
Others/zxing.core/zxing.core/aztec/encoder/HighLevelEncoder.cs
Normal file
383
Others/zxing.core/zxing.core/aztec/encoder/HighLevelEncoder.cs
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
public HighLevelEncoder(byte[] text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the text represented by this High Level Encoder into a BitArray.
|
||||
/// </summary>
|
||||
/// <returns>text represented by this encoder encoded as a <see cref="BitArray"/></returns>
|
||||
public BitArray encode()
|
||||
{
|
||||
ICollection<State> states = new Collection<State>();
|
||||
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<State>() {
|
||||
@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<State> updateStateListForChar(IEnumerable<State> states, int index)
|
||||
{
|
||||
var result = new LinkedList<State>();
|
||||
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<State> 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.
|
||||
var latchState = stateNoBinary.latchAndAppend(mode, charInMode);
|
||||
result.Add(latchState);
|
||||
}
|
||||
// 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.
|
||||
var shiftState = stateNoBinary.shiftAndAppend(mode, charInMode);
|
||||
result.Add(shiftState);
|
||||
}
|
||||
}
|
||||
}
|
||||
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.
|
||||
var binaryState = state.addBinaryShiftChar(index);
|
||||
result.Add(binaryState);
|
||||
}
|
||||
}
|
||||
|
||||
private static ICollection<State> updateStateListForPair(IEnumerable<State> states, int index, int pairCode)
|
||||
{
|
||||
var result = new LinkedList<State>();
|
||||
foreach (State state in states)
|
||||
{
|
||||
updateStateForPair(state, index, pairCode, result);
|
||||
}
|
||||
return simplifyStates(result);
|
||||
}
|
||||
|
||||
private static void updateStateForPair(State state, int index, int pairCode, ICollection<State> 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
|
||||
var digitState = stateNoBinary
|
||||
.latchAndAppend(MODE_DIGIT, 16 - pairCode) // period or comma in DIGIT
|
||||
.latchAndAppend(MODE_DIGIT, 1); // space in DIGIT
|
||||
result.Add(digitState);
|
||||
}
|
||||
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<State> simplifyStates(IEnumerable<State> states)
|
||||
{
|
||||
var result = new LinkedList<State>();
|
||||
var removeList = new List<State>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Others/zxing.core/zxing.core/aztec/encoder/SimpleToken.cs
Normal file
64
Others/zxing.core/zxing.core/aztec/encoder/SimpleToken.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public sealed class SimpleToken : Token
|
||||
{
|
||||
// For normal words, indicates value and bitCount
|
||||
private readonly short value;
|
||||
private readonly short bitCount;
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="previous"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="bitCount"></param>
|
||||
public SimpleToken(Token previous, int value, int bitCount)
|
||||
: base(previous)
|
||||
{
|
||||
this.value = (short)value;
|
||||
this.bitCount = (short)bitCount;
|
||||
}
|
||||
/// <summary>
|
||||
/// append token to bitarray
|
||||
/// </summary>
|
||||
/// <param name="bitArray"></param>
|
||||
/// <param name="text"></param>
|
||||
public override void appendTo(BitArray bitArray, byte[] text)
|
||||
{
|
||||
bitArray.appendBits(value, bitCount);
|
||||
}
|
||||
/// <summary>
|
||||
/// string representation
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
int value = this.value & ((1 << bitCount) - 1);
|
||||
value |= 1 << bitCount;
|
||||
return '<' + SupportClass.ToBinaryString(value | (1 << bitCount)).Substring(1) + '>';
|
||||
}
|
||||
}
|
||||
}
|
||||
219
Others/zxing.core/zxing.core/aztec/encoder/State.cs
Normal file
219
Others/zxing.core/zxing.core/aztec/encoder/State.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// State represents all information about a sequence necessary to generate the current output.
|
||||
/// Note that a state is immutable.
|
||||
/// </summary>
|
||||
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; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new state representing this state with a latch to a (not
|
||||
/// necessary different) mode, and then a code.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new state representing this state, with a temporary shift
|
||||
/// to a different mode to output a single value.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new state representing this state, but an additional character
|
||||
/// output in Binary Shift mode.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the state identical to this one, but we are no longer in
|
||||
/// Binary Shift mode.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if "this" state is better (or equal) to be in than "that"
|
||||
/// state under all possible circumstances.
|
||||
/// </summary>
|
||||
public bool isBetterThanOrEqualTo(State other)
|
||||
{
|
||||
int newModeBitCount = this.bitCount + (HighLevelEncoder.LATCH_TABLE[this.mode][other.mode] >> 16);
|
||||
if (this.binaryShiftByteCount < other.binaryShiftByteCount)
|
||||
{
|
||||
// add additional B/S encoding cost of other, if any
|
||||
newModeBitCount += calculateBinaryShiftCost(other) - calculateBinaryShiftCost(this);
|
||||
}
|
||||
else if (this.binaryShiftByteCount > other.binaryShiftByteCount && other.binaryShiftByteCount > 0)
|
||||
{
|
||||
// maximum possible additional cost (we end up exceeding the 31 byte boundary and other state can stay beneath it)
|
||||
newModeBitCount += 10;
|
||||
}
|
||||
return newModeBitCount <= 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<Token>();
|
||||
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);
|
||||
}
|
||||
|
||||
private static int calculateBinaryShiftCost(State state)
|
||||
{
|
||||
if (state.binaryShiftByteCount > 62)
|
||||
{
|
||||
return 21; // B/S with extended length
|
||||
}
|
||||
if (state.binaryShiftByteCount > 31)
|
||||
{
|
||||
return 20; // two B/S
|
||||
}
|
||||
if (state.binaryShiftByteCount > 0)
|
||||
{
|
||||
return 10; // one B/S
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Others/zxing.core/zxing.core/aztec/encoder/Token.cs
Normal file
77
Others/zxing.core/zxing.core/aztec/encoder/Token.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class Token
|
||||
{
|
||||
/// <summary>
|
||||
/// represents an empty token
|
||||
/// </summary>
|
||||
public static Token EMPTY = new SimpleToken(null, 0, 0);
|
||||
|
||||
private readonly Token previous;
|
||||
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="previous"></param>
|
||||
protected Token(Token previous)
|
||||
{
|
||||
this.previous = previous;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// previous token
|
||||
/// </summary>
|
||||
public Token Previous
|
||||
{
|
||||
get { return previous; }
|
||||
}
|
||||
/// <summary>
|
||||
/// adds a new simple token
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="bitCount"></param>
|
||||
/// <returns></returns>
|
||||
public Token add(int value, int bitCount)
|
||||
{
|
||||
return new SimpleToken(this, value, bitCount);
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="byteCount"></param>
|
||||
/// <returns></returns>
|
||||
public Token addBinaryShift(int start, int byteCount)
|
||||
{
|
||||
int bitCount = (byteCount * 8) + (byteCount <= 31 ? 10 : byteCount <= 62 ? 20 : 21);
|
||||
return new BinaryShiftToken(this, start, byteCount);
|
||||
}
|
||||
/// <summary>
|
||||
/// append to bitarray
|
||||
/// </summary>
|
||||
/// <param name="bitArray"></param>
|
||||
/// <param name="text"></param>
|
||||
public abstract void appendTo(BitArray bitArray, byte[] text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary> <p>See
|
||||
/// <a href="http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/about/s2.html">
|
||||
/// DoCoMo's documentation</a> about the result types represented by subclasses of this class.</p>
|
||||
///
|
||||
/// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
|
||||
/// on exception-based mechanisms during parsing.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
abstract class AbstractDoCoMoResultParser : ResultParser
|
||||
{
|
||||
internal static String[] matchDoCoMoPrefixedField(String prefix, String rawText)
|
||||
{
|
||||
return matchPrefixedField(prefix, rawText, ';', true);
|
||||
}
|
||||
|
||||
internal static String matchSingleDoCoMoPrefixedField(String prefix, String rawText, bool trim)
|
||||
{
|
||||
return matchSinglePrefixedField(prefix, rawText, ';', trim);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary> Implements KDDI AU's address book format. See
|
||||
/// <a href="http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html">
|
||||
/// http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html</a>.
|
||||
/// (Thanks to Yuzo for translating!)
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class AddressBookAUResultParser : ResultParser
|
||||
{
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
var rawText = result.Text;
|
||||
// MEMORY is mandatory; seems like a decent indicator, as does end-of-record separator CR/LF
|
||||
if (rawText == null || rawText.IndexOf("MEMORY") < 0 || rawText.IndexOf("\r\n") < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// NAME1 and NAME2 have specific uses, namely written name and pronunciation, respectively.
|
||||
// Therefore we treat them specially instead of as an array of names.
|
||||
var name = matchSinglePrefixedField("NAME1:", rawText, '\r', true);
|
||||
var pronunciation = matchSinglePrefixedField("NAME2:", rawText, '\r', true);
|
||||
|
||||
var phoneNumbers = matchMultipleValuePrefix("TEL", rawText);
|
||||
var emails = matchMultipleValuePrefix("MAIL", rawText);
|
||||
var note = matchSinglePrefixedField("MEMORY:", rawText, '\r', false);
|
||||
var address = matchSinglePrefixedField("ADD:", rawText, '\r', true);
|
||||
var addresses = address == null ? null : new[] { address };
|
||||
return new AddressBookParsedResult(maybeWrap(name),
|
||||
null,
|
||||
pronunciation,
|
||||
phoneNumbers,
|
||||
null,
|
||||
emails,
|
||||
null,
|
||||
null,
|
||||
note,
|
||||
addresses,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
private static String[] matchMultipleValuePrefix(String prefix, String rawText)
|
||||
{
|
||||
IList<string> values = null;
|
||||
// For now, always 3, and always trim
|
||||
for (int i = 1; i <= 3; i++)
|
||||
{
|
||||
var value = matchSinglePrefixedField(prefix + i + ':', rawText, '\r', true);
|
||||
if (value == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (values == null)
|
||||
{
|
||||
values = new List<string>();
|
||||
}
|
||||
values.Add(value);
|
||||
}
|
||||
if (values == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return SupportClass.toStringArray(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary> Implements the "MECARD" address book entry format.
|
||||
///
|
||||
/// Supported keys: N, SOUND, TEL, EMAIL, NOTE, ADR, BDAY, URL, plus ORG
|
||||
/// Unsupported keys: TEL-AV, NICKNAME
|
||||
///
|
||||
/// Except for TEL, multiple values for keys are also not supported;
|
||||
/// the first one found takes precedence.
|
||||
///
|
||||
/// Our understanding of the MECARD format is based on this document:
|
||||
///
|
||||
/// http://www.mobicode.org.tw/files/OMIA%20Mobile%20Bar%20Code%20Standard%20v3.2.1.doc
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class AddressBookDoCoMoResultParser : AbstractDoCoMoResultParser
|
||||
{
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("MECARD:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String[] rawName = matchDoCoMoPrefixedField("N:", rawText);
|
||||
if (rawName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String name = parseName(rawName[0]);
|
||||
String pronunciation = matchSingleDoCoMoPrefixedField("SOUND:", rawText, true);
|
||||
String[] phoneNumbers = matchDoCoMoPrefixedField("TEL:", rawText);
|
||||
String[] emails = matchDoCoMoPrefixedField("EMAIL:", rawText);
|
||||
String note = matchSingleDoCoMoPrefixedField("NOTE:", rawText, false);
|
||||
String[] addresses = matchDoCoMoPrefixedField("ADR:", rawText);
|
||||
String birthday = matchSingleDoCoMoPrefixedField("BDAY:", rawText, true);
|
||||
if (!isStringOfDigits(birthday, 8))
|
||||
{
|
||||
// No reason to throw out the whole card because the birthday is formatted wrong.
|
||||
birthday = null;
|
||||
}
|
||||
String[] urls = matchDoCoMoPrefixedField("URL:", rawText);
|
||||
|
||||
// Although ORG may not be strictly legal in MECARD, it does exist in VCARD and we might as well
|
||||
// honor it when found in the wild.
|
||||
String org = matchSingleDoCoMoPrefixedField("ORG:", rawText, true);
|
||||
|
||||
return new AddressBookParsedResult(maybeWrap(name),
|
||||
null,
|
||||
pronunciation,
|
||||
phoneNumbers,
|
||||
null,
|
||||
emails,
|
||||
null,
|
||||
null,
|
||||
note,
|
||||
addresses,
|
||||
null,
|
||||
org,
|
||||
birthday,
|
||||
null,
|
||||
urls,
|
||||
null);
|
||||
}
|
||||
|
||||
private static String parseName(String name)
|
||||
{
|
||||
int comma = name.IndexOf(',');
|
||||
if (comma >= 0)
|
||||
{
|
||||
// Format may be last,first; switch it around
|
||||
return name.Substring(comma + 1) + ' ' + name.Substring(0, comma);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes contact information, like that in an address book entry.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class AddressBookParsedResult : ParsedResult
|
||||
{
|
||||
private readonly String[] names;
|
||||
private readonly String[] nicknames;
|
||||
private readonly String pronunciation;
|
||||
private readonly String[] phoneNumbers;
|
||||
private readonly String[] phoneTypes;
|
||||
private readonly String[] emails;
|
||||
private readonly String[] emailTypes;
|
||||
private readonly String instantMessenger;
|
||||
private readonly String note;
|
||||
private readonly String[] addresses;
|
||||
private readonly String[] addressTypes;
|
||||
private readonly String org;
|
||||
private readonly String birthday;
|
||||
private readonly String title;
|
||||
private readonly String[] urls;
|
||||
private readonly String[] geo;
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="names"></param>
|
||||
/// <param name="phoneNumbers"></param>
|
||||
/// <param name="phoneTypes"></param>
|
||||
/// <param name="emails"></param>
|
||||
/// <param name="emailTypes"></param>
|
||||
/// <param name="addresses"></param>
|
||||
/// <param name="addressTypes"></param>
|
||||
public AddressBookParsedResult(String[] names,
|
||||
String[] phoneNumbers,
|
||||
String[] phoneTypes,
|
||||
String[] emails,
|
||||
String[] emailTypes,
|
||||
String[] addresses,
|
||||
String[] addressTypes)
|
||||
: this(names,
|
||||
null,
|
||||
null,
|
||||
phoneNumbers,
|
||||
phoneTypes,
|
||||
emails,
|
||||
emailTypes,
|
||||
null,
|
||||
null,
|
||||
addresses,
|
||||
addressTypes,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="names"></param>
|
||||
/// <param name="nicknames"></param>
|
||||
/// <param name="pronunciation"></param>
|
||||
/// <param name="phoneNumbers"></param>
|
||||
/// <param name="phoneTypes"></param>
|
||||
/// <param name="emails"></param>
|
||||
/// <param name="emailTypes"></param>
|
||||
/// <param name="instantMessenger"></param>
|
||||
/// <param name="note"></param>
|
||||
/// <param name="addresses"></param>
|
||||
/// <param name="addressTypes"></param>
|
||||
/// <param name="org"></param>
|
||||
/// <param name="birthday"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="urls"></param>
|
||||
/// <param name="geo"></param>
|
||||
public AddressBookParsedResult(String[] names,
|
||||
String[] nicknames,
|
||||
String pronunciation,
|
||||
String[] phoneNumbers,
|
||||
String[] phoneTypes,
|
||||
String[] emails,
|
||||
String[] emailTypes,
|
||||
String instantMessenger,
|
||||
String note,
|
||||
String[] addresses,
|
||||
String[] addressTypes,
|
||||
String org,
|
||||
String birthday,
|
||||
String title,
|
||||
String[] urls,
|
||||
String[] geo)
|
||||
: base(ParsedResultType.ADDRESSBOOK)
|
||||
{
|
||||
if (phoneNumbers != null && phoneTypes != null && phoneNumbers.Length != phoneTypes.Length)
|
||||
{
|
||||
throw new ArgumentException("Phone numbers and types lengths differ");
|
||||
}
|
||||
if (emails != null && emailTypes != null && emails.Length != emailTypes.Length)
|
||||
{
|
||||
throw new ArgumentException("Emails and types lengths differ");
|
||||
}
|
||||
if (addresses != null && addressTypes != null && addresses.Length != addressTypes.Length)
|
||||
{
|
||||
throw new ArgumentException("Addresses and types lengths differ");
|
||||
}
|
||||
|
||||
this.names = names;
|
||||
this.nicknames = nicknames;
|
||||
this.pronunciation = pronunciation;
|
||||
this.phoneNumbers = phoneNumbers;
|
||||
this.phoneTypes = phoneTypes;
|
||||
this.emails = emails;
|
||||
this.emailTypes = emailTypes;
|
||||
this.instantMessenger = instantMessenger;
|
||||
this.note = note;
|
||||
this.addresses = addresses;
|
||||
this.addressTypes = addressTypes;
|
||||
this.org = org;
|
||||
this.birthday = birthday;
|
||||
this.title = title;
|
||||
this.urls = urls;
|
||||
this.geo = geo;
|
||||
|
||||
displayResultValue = getDisplayResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the names
|
||||
/// </summary>
|
||||
public String[] Names
|
||||
{
|
||||
get { return names; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the nicknames
|
||||
/// </summary>
|
||||
public String[] Nicknames
|
||||
{
|
||||
get { return nicknames; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In Japanese, the name is written in kanji, which can have multiple readings. Therefore a hint
|
||||
/// is often provided, called furigana, which spells the name phonetically.
|
||||
/// </summary>
|
||||
/// <return>The pronunciation of the getNames() field, often in hiragana or katakana.</return>
|
||||
public String Pronunciation
|
||||
{
|
||||
get { return pronunciation; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the phone numbers
|
||||
/// </summary>
|
||||
public String[] PhoneNumbers
|
||||
{
|
||||
get { return phoneNumbers; }
|
||||
}
|
||||
|
||||
/// <return>optional descriptions of the type of each phone number. It could be like "HOME", but,
|
||||
/// there is no guaranteed or standard format.</return>
|
||||
public String[] PhoneTypes
|
||||
{
|
||||
get { return phoneTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the e-mail addresses
|
||||
/// </summary>
|
||||
public String[] Emails
|
||||
{
|
||||
get { return emails; }
|
||||
}
|
||||
|
||||
/// <return>optional descriptions of the type of each e-mail. It could be like "WORK", but,
|
||||
/// there is no guaranteed or standard format.</return>
|
||||
public String[] EmailTypes
|
||||
{
|
||||
get { return emailTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the instant messenger addresses
|
||||
/// </summary>
|
||||
public String InstantMessenger
|
||||
{
|
||||
get { return instantMessenger; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the note field
|
||||
/// </summary>
|
||||
public String Note
|
||||
{
|
||||
get { return note; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the addresses
|
||||
/// </summary>
|
||||
public String[] Addresses
|
||||
{
|
||||
get { return addresses; }
|
||||
}
|
||||
|
||||
/// <return>optional descriptions of the type of each e-mail. It could be like "WORK", but,
|
||||
/// there is no guaranteed or standard format.</return>
|
||||
public String[] AddressTypes
|
||||
{
|
||||
get { return addressTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the title
|
||||
/// </summary>
|
||||
public String Title
|
||||
{
|
||||
get { return title; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the organisations
|
||||
/// </summary>
|
||||
public String Org
|
||||
{
|
||||
get { return org; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the urls
|
||||
/// </summary>
|
||||
public String[] URLs
|
||||
{
|
||||
get { return urls; }
|
||||
}
|
||||
|
||||
/// <return>birthday formatted as yyyyMMdd (e.g. 19780917)</return>
|
||||
public String Birthday
|
||||
{
|
||||
get { return birthday; }
|
||||
}
|
||||
|
||||
/// <return>a location as a latitude/longitude pair</return>
|
||||
public String[] Geo
|
||||
{
|
||||
get { return geo; }
|
||||
}
|
||||
|
||||
private String getDisplayResult()
|
||||
{
|
||||
var result = new StringBuilder(100);
|
||||
maybeAppend(names, result);
|
||||
maybeAppend(nicknames, result);
|
||||
maybeAppend(pronunciation, result);
|
||||
maybeAppend(title, result);
|
||||
maybeAppend(org, result);
|
||||
maybeAppend(addresses, result);
|
||||
maybeAppend(phoneNumbers, result);
|
||||
maybeAppend(emails, result);
|
||||
maybeAppend(instantMessenger, result);
|
||||
maybeAppend(urls, result);
|
||||
maybeAppend(birthday, result);
|
||||
maybeAppend(geo, result);
|
||||
maybeAppend(note, result);
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary> Implements the "BIZCARD" address book entry format, though this has been
|
||||
/// largely reverse-engineered from examples observed in the wild -- still
|
||||
/// looking for a definitive reference.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class BizcardResultParser : AbstractDoCoMoResultParser
|
||||
{
|
||||
// Yes, we extend AbstractDoCoMoResultParser since the format is very much
|
||||
// like the DoCoMo MECARD format, but this is not technically one of
|
||||
// DoCoMo's proposed formats
|
||||
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("BIZCARD:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String firstName = matchSingleDoCoMoPrefixedField("N:", rawText, true);
|
||||
String lastName = matchSingleDoCoMoPrefixedField("X:", rawText, true);
|
||||
String fullName = buildName(firstName, lastName);
|
||||
String title = matchSingleDoCoMoPrefixedField("T:", rawText, true);
|
||||
String org = matchSingleDoCoMoPrefixedField("C:", rawText, true);
|
||||
String[] addresses = matchDoCoMoPrefixedField("A:", rawText);
|
||||
String phoneNumber1 = matchSingleDoCoMoPrefixedField("B:", rawText, true);
|
||||
String phoneNumber2 = matchSingleDoCoMoPrefixedField("M:", rawText, true);
|
||||
String phoneNumber3 = matchSingleDoCoMoPrefixedField("F:", rawText, true);
|
||||
String email = matchSingleDoCoMoPrefixedField("E:", rawText, true);
|
||||
|
||||
return new AddressBookParsedResult(maybeWrap(fullName),
|
||||
null,
|
||||
null,
|
||||
buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3),
|
||||
null,
|
||||
maybeWrap(email),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
addresses,
|
||||
null,
|
||||
org,
|
||||
null,
|
||||
title,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
private static String[] buildPhoneNumbers(String number1, String number2, String number3)
|
||||
{
|
||||
var numbers = new List<string>();
|
||||
if (number1 != null)
|
||||
{
|
||||
numbers.Add(number1);
|
||||
}
|
||||
if (number2 != null)
|
||||
{
|
||||
numbers.Add(number2);
|
||||
}
|
||||
if (number3 != null)
|
||||
{
|
||||
numbers.Add(number3);
|
||||
}
|
||||
var size = numbers.Count;
|
||||
if (size == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return SupportClass.toStringArray(numbers);
|
||||
}
|
||||
|
||||
private static String buildName(String firstName, String lastName)
|
||||
{
|
||||
if (firstName == null)
|
||||
{
|
||||
return lastName;
|
||||
}
|
||||
return lastName == null ? firstName : firstName + ' ' + lastName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class BookmarkDoCoMoResultParser : AbstractDoCoMoResultParser
|
||||
{
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null || !rawText.StartsWith("MEBKM:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String title = matchSingleDoCoMoPrefixedField("TITLE:", rawText, true);
|
||||
String[] rawUri = matchDoCoMoPrefixedField("URL:", rawText);
|
||||
if (rawUri == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String uri = rawUri[0];
|
||||
if (!URIResultParser.isBasicallyValidURI(uri))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new URIParsedResult(uri, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* 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.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes a calendar event at a certain time, optionally with attendees and a location.
|
||||
/// </summary>
|
||||
///<author>Sean Owen</author>
|
||||
public sealed class CalendarParsedResult : ParsedResult
|
||||
{
|
||||
private static readonly Regex RFC2445_DURATION =
|
||||
new Regex(@"\A(?:" + "P(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?" + @")\z"
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
|
||||
private static readonly long[] RFC2445_DURATION_FIELD_UNITS =
|
||||
{
|
||||
7*24*60*60*1000L, // 1 week
|
||||
24*60*60*1000L, // 1 day
|
||||
60*60*1000L, // 1 hour
|
||||
60*1000L, // 1 minute
|
||||
1000L, // 1 second
|
||||
};
|
||||
|
||||
private static readonly Regex DATE_TIME = new Regex(@"\A(?:" + "[0-9]{8}(T[0-9]{6}Z?)?" + @")\z"
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
|
||||
private readonly String summary;
|
||||
private readonly DateTime start;
|
||||
private readonly bool startAllDay;
|
||||
private readonly DateTime? end;
|
||||
private readonly bool endAllDay;
|
||||
private readonly String location;
|
||||
private readonly String organizer;
|
||||
private readonly String[] attendees;
|
||||
private readonly String description;
|
||||
private readonly double latitude;
|
||||
private readonly double longitude;
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="summary"></param>
|
||||
/// <param name="startString"></param>
|
||||
/// <param name="endString"></param>
|
||||
/// <param name="durationString"></param>
|
||||
/// <param name="location"></param>
|
||||
/// <param name="organizer"></param>
|
||||
/// <param name="attendees"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <param name="latitude"></param>
|
||||
/// <param name="longitude"></param>
|
||||
public CalendarParsedResult(String summary,
|
||||
String startString,
|
||||
String endString,
|
||||
String durationString,
|
||||
String location,
|
||||
String organizer,
|
||||
String[] attendees,
|
||||
String description,
|
||||
double latitude,
|
||||
double longitude)
|
||||
: base(ParsedResultType.CALENDAR)
|
||||
{
|
||||
this.summary = summary;
|
||||
try
|
||||
{
|
||||
this.start = parseDate(startString);
|
||||
}
|
||||
catch (Exception pe)
|
||||
{
|
||||
throw new ArgumentException(pe.ToString());
|
||||
}
|
||||
|
||||
if (endString == null)
|
||||
{
|
||||
long durationMS = parseDurationMS(durationString);
|
||||
end = durationMS < 0L ? null : (DateTime?)start + new TimeSpan(0, 0, 0, 0, (int)durationMS);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
this.end = parseDate(endString);
|
||||
}
|
||||
catch (Exception pe)
|
||||
{
|
||||
throw new ArgumentException(pe.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
this.startAllDay = startString.Length == 8;
|
||||
this.endAllDay = endString != null && endString.Length == 8;
|
||||
|
||||
this.location = location;
|
||||
this.organizer = organizer;
|
||||
this.attendees = attendees;
|
||||
this.description = description;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
|
||||
var result = new StringBuilder(100);
|
||||
maybeAppend(summary, result);
|
||||
maybeAppend(format(startAllDay, start), result);
|
||||
maybeAppend(format(endAllDay, end), result);
|
||||
maybeAppend(location, result);
|
||||
maybeAppend(organizer, result);
|
||||
maybeAppend(attendees, result);
|
||||
maybeAppend(description, result);
|
||||
displayResultValue = result.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// summary
|
||||
/// </summary>
|
||||
public String Summary
|
||||
{
|
||||
get { return summary; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the start.
|
||||
/// </summary>
|
||||
public DateTime Start
|
||||
{
|
||||
get { return start; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is start all day].
|
||||
/// </summary>
|
||||
/// <returns>if start time was specified as a whole day</returns>
|
||||
public bool isStartAllDay()
|
||||
{
|
||||
return startAllDay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// event end <see cref="DateTime"/>, or null if event has no duration
|
||||
/// </summary>
|
||||
public DateTime? End
|
||||
{
|
||||
get { return end; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is end all day.
|
||||
/// </summary>
|
||||
/// <value>true if end time was specified as a whole day</value>
|
||||
public bool isEndAllDay
|
||||
{
|
||||
get { return endAllDay; }
|
||||
}
|
||||
/// <summary>
|
||||
/// location
|
||||
/// </summary>
|
||||
public String Location
|
||||
{
|
||||
get { return location; }
|
||||
}
|
||||
/// <summary>
|
||||
/// organizer
|
||||
/// </summary>
|
||||
public String Organizer
|
||||
{
|
||||
get { return organizer; }
|
||||
}
|
||||
/// <summary>
|
||||
/// attendees
|
||||
/// </summary>
|
||||
public String[] Attendees
|
||||
{
|
||||
get { return attendees; }
|
||||
}
|
||||
/// <summary>
|
||||
/// description
|
||||
/// </summary>
|
||||
public String Description
|
||||
{
|
||||
get { return description; }
|
||||
}
|
||||
/// <summary>
|
||||
/// latitude
|
||||
/// </summary>
|
||||
public double Latitude
|
||||
{
|
||||
get { return latitude; }
|
||||
}
|
||||
/// <summary>
|
||||
/// longitude
|
||||
/// </summary>
|
||||
public double Longitude
|
||||
{
|
||||
get { return longitude; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a string as a date. RFC 2445 allows the start and end fields to be of type DATE (e.g. 20081021)
|
||||
/// or DATE-TIME (e.g. 20081021T123000 for local time, or 20081021T123000Z for UTC).
|
||||
/// </summary>
|
||||
/// <param name="when">The string to parse</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException">if not a date formatted string</exception>
|
||||
private static DateTime parseDate(String when)
|
||||
{
|
||||
if (!DATE_TIME.Match(when).Success)
|
||||
{
|
||||
throw new ArgumentException(String.Format("no date format: {0}", when));
|
||||
}
|
||||
if (when.Length == 8)
|
||||
{
|
||||
// Show only year/month/day
|
||||
// For dates without a time, for purposes of interacting with Android, the resulting timestamp
|
||||
// needs to be midnight of that day in GMT. See:
|
||||
// http://code.google.com/p/android/issues/detail?id=8330
|
||||
// format.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
return DateTime.ParseExact(when, "yyyyMMdd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
// The when string can be local time, or UTC if it ends with a Z
|
||||
if (when.Length == 16 && when[15] == 'Z')
|
||||
{
|
||||
var milliseconds = parseDateTimeString(when.Substring(0, 15));
|
||||
//Calendar calendar = new GregorianCalendar();
|
||||
// Account for time zone difference
|
||||
//milliseconds += calendar.get(Calendar.ZONE_OFFSET);
|
||||
// Might need to correct for daylight savings time, but use target time since
|
||||
// now might be in DST but not then, or vice versa
|
||||
//calendar.setTime(new Date(milliseconds));
|
||||
//return milliseconds + calendar.get(Calendar.DST_OFFSET);
|
||||
milliseconds = TimeZoneInfo.ConvertTime(milliseconds, TimeZoneInfo.Local);
|
||||
return milliseconds;
|
||||
}
|
||||
return parseDateTimeString(when);
|
||||
}
|
||||
|
||||
private static String format(bool allDay, DateTime? date)
|
||||
{
|
||||
if (date == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (allDay)
|
||||
return date.Value.ToString("D", CultureInfo.CurrentCulture);
|
||||
return date.Value.ToString("F", CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
private static long parseDurationMS(String durationString)
|
||||
{
|
||||
if (durationString == null)
|
||||
{
|
||||
return -1L;
|
||||
}
|
||||
var m = RFC2445_DURATION.Match(durationString);
|
||||
if (!m.Success)
|
||||
{
|
||||
return -1L;
|
||||
}
|
||||
long durationMS = 0L;
|
||||
for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.Length; i++)
|
||||
{
|
||||
String fieldValue = m.Groups[i + 1].Value;
|
||||
if (!String.IsNullOrEmpty(fieldValue))
|
||||
{
|
||||
durationMS += RFC2445_DURATION_FIELD_UNITS[i] * Int32.Parse(fieldValue);
|
||||
}
|
||||
}
|
||||
return durationMS;
|
||||
}
|
||||
|
||||
private static DateTime parseDateTimeString(String dateTimeString)
|
||||
{
|
||||
return DateTime.ParseExact(dateTimeString, "yyyyMMdd'T'HHmmss", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes an email message including recipients, subject and body text.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class EmailAddressParsedResult : ParsedResult
|
||||
{
|
||||
/// <summary>
|
||||
/// the email address
|
||||
/// </summary>
|
||||
public String EmailAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return Tos == null || Tos.Length == 0 ? null : Tos[0];
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// the TOs
|
||||
/// </summary>
|
||||
public String[] Tos { get; private set; }
|
||||
/// <summary>
|
||||
/// the CCs
|
||||
/// </summary>
|
||||
public String[] CCs { get; private set; }
|
||||
/// <summary>
|
||||
/// the BCCs
|
||||
/// </summary>
|
||||
public String[] BCCs { get; private set; }
|
||||
/// <summary>
|
||||
/// the subject
|
||||
/// </summary>
|
||||
public String Subject { get; private set; }
|
||||
/// <summary>
|
||||
/// the body
|
||||
/// </summary>
|
||||
public String Body { get; private set; }
|
||||
/// <summary>
|
||||
/// the mailto: uri
|
||||
/// </summary>
|
||||
[Obsolete("deprecated without replacement")]
|
||||
public String MailtoURI { get { return "mailto:"; } }
|
||||
|
||||
internal EmailAddressParsedResult(String to)
|
||||
: this(new[] { to }, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal EmailAddressParsedResult(String[] tos,
|
||||
String[] ccs,
|
||||
String[] bccs,
|
||||
String subject,
|
||||
String body)
|
||||
: base(ParsedResultType.EMAIL_ADDRESS)
|
||||
{
|
||||
Tos = tos;
|
||||
CCs = ccs;
|
||||
BCCs = bccs;
|
||||
Subject = subject;
|
||||
Body = body;
|
||||
|
||||
var result = new StringBuilder(30);
|
||||
maybeAppend(Tos, result);
|
||||
maybeAppend(CCs, result);
|
||||
maybeAppend(BCCs, result);
|
||||
maybeAppend(Subject, result);
|
||||
maybeAppend(Body, result);
|
||||
displayResultValue = result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.RegularExpressions;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a result that encodes an e-mail address, either as a plain address
|
||||
/// like "joe@example.org" or a mailto: URL like "mailto:joe@example.org".
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
internal sealed class EmailAddressResultParser : ResultParser
|
||||
{
|
||||
private static readonly Regex COMMA = new Regex(","
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
|
||||
public override ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (rawText.ToLower().StartsWith("mailto:"))
|
||||
{
|
||||
// If it starts with mailto:, assume it is definitely trying to be an email address
|
||||
String hostEmail = rawText.Substring(7);
|
||||
int queryStart = hostEmail.IndexOf('?');
|
||||
if (queryStart >= 0)
|
||||
{
|
||||
hostEmail = hostEmail.Substring(0, queryStart);
|
||||
}
|
||||
hostEmail = urlDecode(hostEmail);
|
||||
String[] tos = null;
|
||||
if (!String.IsNullOrEmpty(hostEmail))
|
||||
{
|
||||
tos = COMMA.Split(hostEmail);
|
||||
}
|
||||
var nameValues = parseNameValuePairs(rawText);
|
||||
String[] ccs = null;
|
||||
String[] bccs = null;
|
||||
String subject = null;
|
||||
String body = null;
|
||||
if (nameValues != null)
|
||||
{
|
||||
if (tos == null)
|
||||
{
|
||||
String tosString;
|
||||
if (nameValues.TryGetValue("to", out tosString) && tosString != null)
|
||||
{
|
||||
tos = COMMA.Split(tosString);
|
||||
}
|
||||
}
|
||||
String ccString;
|
||||
if (nameValues.TryGetValue("cc", out ccString) && ccString != null)
|
||||
{
|
||||
ccs = COMMA.Split(ccString);
|
||||
}
|
||||
String bccString;
|
||||
if (nameValues.TryGetValue("bcc", out bccString) && bccString != null)
|
||||
{
|
||||
bccs = COMMA.Split(bccString);
|
||||
}
|
||||
nameValues.TryGetValue("subject", out subject);
|
||||
nameValues.TryGetValue("body", out body);
|
||||
}
|
||||
return new EmailAddressParsedResult(tos, ccs, bccs, subject, body);
|
||||
}
|
||||
if (!EmailDoCoMoResultParser.isBasicallyValidEmailAddress(rawText))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new EmailAddressParsedResult(rawText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2007 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the "MATMSG" email message entry format.
|
||||
///
|
||||
/// Supported keys: TO, SUB, BODY
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
internal sealed class EmailDoCoMoResultParser : AbstractDoCoMoResultParser
|
||||
{
|
||||
private static readonly Regex ATEXT_ALPHANUMERIC = new Regex(@"\A(?:" + "[a-zA-Z0-9@.!#$%&'*+\\-/=?^_`{|}~]+" + @")\z"
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
|
||||
public override ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
var rawText = result.Text;
|
||||
if (!rawText.StartsWith("MATMSG:"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var tos = matchDoCoMoPrefixedField("TO:", rawText);
|
||||
if (tos == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
for (var index = 0; index < tos.Length; index++)
|
||||
{
|
||||
var to = tos[index];
|
||||
if (!isBasicallyValidEmailAddress(to))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
var subject = matchSingleDoCoMoPrefixedField("SUB:", rawText, false);
|
||||
var body = matchSingleDoCoMoPrefixedField("BODY:", rawText, false);
|
||||
return new EmailAddressParsedResult(tos, null, null, subject, body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This implements only the most basic checking for an email address's validity -- that it contains
|
||||
/// an '@' and contains no characters disallowed by RFC 2822. This is an overly lenient definition of
|
||||
/// validity. We want to generally be lenient here since this class is only intended to encapsulate what's
|
||||
/// in a barcode, not "judge" it.
|
||||
/// </summary>
|
||||
/// <param name="email">The email.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if it is basically a valid email address; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
internal static bool isBasicallyValidEmailAddress(String email)
|
||||
{
|
||||
return email != null && ATEXT_ALPHANUMERIC.Match(email).Success && email.IndexOf('@') >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes extended product information as encoded by the RSS format, like weight, price, dates, etc.
|
||||
/// </summary>
|
||||
/// <author> Antonio Manuel Benjumea Conde, Servinform, S.A.</author>
|
||||
/// <author> Agustín Delgado, Servinform, S.A.</author>
|
||||
public class ExpandedProductParsedResult : ParsedResult
|
||||
{
|
||||
/// <summary>
|
||||
/// extension for kilogram weight type
|
||||
/// </summary>
|
||||
public static String KILOGRAM = "KG";
|
||||
/// <summary>
|
||||
/// extension for pounds weight type
|
||||
/// </summary>
|
||||
public static String POUND = "LB";
|
||||
|
||||
private readonly String rawText;
|
||||
private readonly String productID;
|
||||
private readonly String sscc;
|
||||
private readonly String lotNumber;
|
||||
private readonly String productionDate;
|
||||
private readonly String packagingDate;
|
||||
private readonly String bestBeforeDate;
|
||||
private readonly String expirationDate;
|
||||
private readonly String weight;
|
||||
private readonly String weightType;
|
||||
private readonly String weightIncrement;
|
||||
private readonly String price;
|
||||
private readonly String priceIncrement;
|
||||
private readonly String priceCurrency;
|
||||
// For AIS that not exist in this object
|
||||
private readonly IDictionary<String, String> uncommonAIs;
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="rawText"></param>
|
||||
/// <param name="productID"></param>
|
||||
/// <param name="sscc"></param>
|
||||
/// <param name="lotNumber"></param>
|
||||
/// <param name="productionDate"></param>
|
||||
/// <param name="packagingDate"></param>
|
||||
/// <param name="bestBeforeDate"></param>
|
||||
/// <param name="expirationDate"></param>
|
||||
/// <param name="weight"></param>
|
||||
/// <param name="weightType"></param>
|
||||
/// <param name="weightIncrement"></param>
|
||||
/// <param name="price"></param>
|
||||
/// <param name="priceIncrement"></param>
|
||||
/// <param name="priceCurrency"></param>
|
||||
/// <param name="uncommonAIs"></param>
|
||||
public ExpandedProductParsedResult(String rawText,
|
||||
String productID,
|
||||
String sscc,
|
||||
String lotNumber,
|
||||
String productionDate,
|
||||
String packagingDate,
|
||||
String bestBeforeDate,
|
||||
String expirationDate,
|
||||
String weight,
|
||||
String weightType,
|
||||
String weightIncrement,
|
||||
String price,
|
||||
String priceIncrement,
|
||||
String priceCurrency,
|
||||
IDictionary<String, String> uncommonAIs)
|
||||
: base(ParsedResultType.PRODUCT)
|
||||
{
|
||||
this.rawText = rawText;
|
||||
this.productID = productID;
|
||||
this.sscc = sscc;
|
||||
this.lotNumber = lotNumber;
|
||||
this.productionDate = productionDate;
|
||||
this.packagingDate = packagingDate;
|
||||
this.bestBeforeDate = bestBeforeDate;
|
||||
this.expirationDate = expirationDate;
|
||||
this.weight = weight;
|
||||
this.weightType = weightType;
|
||||
this.weightIncrement = weightIncrement;
|
||||
this.price = price;
|
||||
this.priceIncrement = priceIncrement;
|
||||
this.priceCurrency = priceCurrency;
|
||||
this.uncommonAIs = uncommonAIs;
|
||||
|
||||
displayResultValue = productID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(Object o)
|
||||
{
|
||||
if (!(o is ExpandedProductParsedResult))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var other = (ExpandedProductParsedResult)o;
|
||||
|
||||
return equalsOrNull(productID, other.productID)
|
||||
&& equalsOrNull(sscc, other.sscc)
|
||||
&& equalsOrNull(lotNumber, other.lotNumber)
|
||||
&& equalsOrNull(productionDate, other.productionDate)
|
||||
&& equalsOrNull(bestBeforeDate, other.bestBeforeDate)
|
||||
&& equalsOrNull(expirationDate, other.expirationDate)
|
||||
&& equalsOrNull(weight, other.weight)
|
||||
&& equalsOrNull(weightType, other.weightType)
|
||||
&& equalsOrNull(weightIncrement, other.weightIncrement)
|
||||
&& equalsOrNull(price, other.price)
|
||||
&& equalsOrNull(priceIncrement, other.priceIncrement)
|
||||
&& equalsOrNull(priceCurrency, other.priceCurrency)
|
||||
&& equalsOrNull(uncommonAIs, other.uncommonAIs);
|
||||
}
|
||||
|
||||
private static bool equalsOrNull(Object o1, Object o2)
|
||||
{
|
||||
return o1 == null ? o2 == null : o1.Equals(o2);
|
||||
}
|
||||
|
||||
private static bool equalsOrNull(IDictionary<String, String> o1, IDictionary<String, String> o2)
|
||||
{
|
||||
if (o1 == null)
|
||||
return o2 == null;
|
||||
if (o1.Count != o2.Count)
|
||||
return false;
|
||||
foreach (var entry in o1)
|
||||
{
|
||||
if (!o2.ContainsKey(entry.Key))
|
||||
return false;
|
||||
if (!entry.Value.Equals(o2[entry.Key]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 0;
|
||||
hash ^= hashNotNull(productID);
|
||||
hash ^= hashNotNull(sscc);
|
||||
hash ^= hashNotNull(lotNumber);
|
||||
hash ^= hashNotNull(productionDate);
|
||||
hash ^= hashNotNull(bestBeforeDate);
|
||||
hash ^= hashNotNull(expirationDate);
|
||||
hash ^= hashNotNull(weight);
|
||||
hash ^= hashNotNull(weightType);
|
||||
hash ^= hashNotNull(weightIncrement);
|
||||
hash ^= hashNotNull(price);
|
||||
hash ^= hashNotNull(priceIncrement);
|
||||
hash ^= hashNotNull(priceCurrency);
|
||||
hash ^= hashNotNull(uncommonAIs);
|
||||
return hash;
|
||||
}
|
||||
|
||||
private static int hashNotNull(Object o)
|
||||
{
|
||||
return o == null ? 0 : o.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the raw text
|
||||
/// </summary>
|
||||
public String RawText
|
||||
{
|
||||
get { return rawText; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the product id
|
||||
/// </summary>
|
||||
public String ProductID
|
||||
{
|
||||
get { return productID; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the sscc
|
||||
/// </summary>
|
||||
public String Sscc
|
||||
{
|
||||
get { return sscc; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the lot number
|
||||
/// </summary>
|
||||
public String LotNumber
|
||||
{
|
||||
get { return lotNumber; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the production date
|
||||
/// </summary>
|
||||
public String ProductionDate
|
||||
{
|
||||
get { return productionDate; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the packaging date
|
||||
/// </summary>
|
||||
public String PackagingDate
|
||||
{
|
||||
get { return packagingDate; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the best before date
|
||||
/// </summary>
|
||||
public String BestBeforeDate
|
||||
{
|
||||
get { return bestBeforeDate; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the expiration date
|
||||
/// </summary>
|
||||
public String ExpirationDate
|
||||
{
|
||||
get { return expirationDate; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the weight
|
||||
/// </summary>
|
||||
public String Weight
|
||||
{
|
||||
get { return weight; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the weight type
|
||||
/// </summary>
|
||||
public String WeightType
|
||||
{
|
||||
get { return weightType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the weight increment
|
||||
/// </summary>
|
||||
public String WeightIncrement
|
||||
{
|
||||
get { return weightIncrement; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the price
|
||||
/// </summary>
|
||||
public String Price
|
||||
{
|
||||
get { return price; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the price increment
|
||||
/// </summary>
|
||||
public String PriceIncrement
|
||||
{
|
||||
get { return priceIncrement; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the price currency
|
||||
/// </summary>
|
||||
public String PriceCurrency
|
||||
{
|
||||
get { return priceCurrency; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the uncommon AIs
|
||||
/// </summary>
|
||||
public IDictionary<String, String> UncommonAIs
|
||||
{
|
||||
get { return uncommonAIs; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the display representation (raw text)
|
||||
/// </summary>
|
||||
public override string DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return rawText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses strings of digits that represent a RSS Extended code.
|
||||
/// </summary>
|
||||
/// <author>Antonio Manuel Benjumea Conde, Servinform, S.A.</author>
|
||||
/// <author>Agustín Delgado, Servinform, S.A.</author>
|
||||
public class ExpandedProductResultParser : ResultParser
|
||||
{
|
||||
/// <summary>
|
||||
/// tries to parse a text representation to a specific result object
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public override ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
BarcodeFormat format = result.BarcodeFormat;
|
||||
if (format != BarcodeFormat.RSS_EXPANDED)
|
||||
{
|
||||
// ExtendedProductParsedResult NOT created. Not a RSS Expanded barcode
|
||||
return null;
|
||||
}
|
||||
String rawText = result.Text;
|
||||
|
||||
String productID = null;
|
||||
String sscc = null;
|
||||
String lotNumber = null;
|
||||
String productionDate = null;
|
||||
String packagingDate = null;
|
||||
String bestBeforeDate = null;
|
||||
String expirationDate = null;
|
||||
String weight = null;
|
||||
String weightType = null;
|
||||
String weightIncrement = null;
|
||||
String price = null;
|
||||
String priceIncrement = null;
|
||||
String priceCurrency = null;
|
||||
var uncommonAIs = new Dictionary<String, String>();
|
||||
|
||||
int i = 0;
|
||||
|
||||
while (i < rawText.Length)
|
||||
{
|
||||
String ai = findAIvalue(i, rawText);
|
||||
if (ai == null)
|
||||
{
|
||||
// Error. Code doesn't match with RSS expanded pattern
|
||||
// ExtendedProductParsedResult NOT created. Not match with RSS Expanded pattern
|
||||
return null;
|
||||
}
|
||||
i += ai.Length + 2;
|
||||
String value = findValue(i, rawText);
|
||||
i += value.Length;
|
||||
|
||||
if ("00".Equals(ai))
|
||||
{
|
||||
sscc = value;
|
||||
}
|
||||
else if ("01".Equals(ai))
|
||||
{
|
||||
productID = value;
|
||||
}
|
||||
else if ("10".Equals(ai))
|
||||
{
|
||||
lotNumber = value;
|
||||
}
|
||||
else if ("11".Equals(ai))
|
||||
{
|
||||
productionDate = value;
|
||||
}
|
||||
else if ("13".Equals(ai))
|
||||
{
|
||||
packagingDate = value;
|
||||
}
|
||||
else if ("15".Equals(ai))
|
||||
{
|
||||
bestBeforeDate = value;
|
||||
}
|
||||
else if ("17".Equals(ai))
|
||||
{
|
||||
expirationDate = value;
|
||||
}
|
||||
else if ("3100".Equals(ai) || "3101".Equals(ai)
|
||||
|| "3102".Equals(ai) || "3103".Equals(ai)
|
||||
|| "3104".Equals(ai) || "3105".Equals(ai)
|
||||
|| "3106".Equals(ai) || "3107".Equals(ai)
|
||||
|| "3108".Equals(ai) || "3109".Equals(ai))
|
||||
{
|
||||
weight = value;
|
||||
weightType = ExpandedProductParsedResult.KILOGRAM;
|
||||
weightIncrement = ai.Substring(3);
|
||||
}
|
||||
else if ("3200".Equals(ai) || "3201".Equals(ai)
|
||||
|| "3202".Equals(ai) || "3203".Equals(ai)
|
||||
|| "3204".Equals(ai) || "3205".Equals(ai)
|
||||
|| "3206".Equals(ai) || "3207".Equals(ai)
|
||||
|| "3208".Equals(ai) || "3209".Equals(ai))
|
||||
{
|
||||
weight = value;
|
||||
weightType = ExpandedProductParsedResult.POUND;
|
||||
weightIncrement = ai.Substring(3);
|
||||
}
|
||||
else if ("3920".Equals(ai) || "3921".Equals(ai)
|
||||
|| "3922".Equals(ai) || "3923".Equals(ai))
|
||||
{
|
||||
price = value;
|
||||
priceIncrement = ai.Substring(3);
|
||||
}
|
||||
else if ("3930".Equals(ai) || "3931".Equals(ai)
|
||||
|| "3932".Equals(ai) || "3933".Equals(ai))
|
||||
{
|
||||
if (value.Length < 4)
|
||||
{
|
||||
// The value must have more of 3 symbols (3 for currency and
|
||||
// 1 at least for the price)
|
||||
// ExtendedProductParsedResult NOT created. Not match with RSS Expanded pattern
|
||||
return null;
|
||||
}
|
||||
price = value.Substring(3);
|
||||
priceCurrency = value.Substring(0, 3);
|
||||
priceIncrement = ai.Substring(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match with common AIs
|
||||
uncommonAIs[ai] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return new ExpandedProductParsedResult(rawText,
|
||||
productID,
|
||||
sscc,
|
||||
lotNumber,
|
||||
productionDate,
|
||||
packagingDate,
|
||||
bestBeforeDate,
|
||||
expirationDate,
|
||||
weight,
|
||||
weightType,
|
||||
weightIncrement,
|
||||
price,
|
||||
priceIncrement,
|
||||
priceCurrency,
|
||||
uncommonAIs);
|
||||
}
|
||||
|
||||
private static String findAIvalue(int i, String rawText)
|
||||
{
|
||||
char c = rawText[i];
|
||||
// First character must be a open parenthesis.If not, ERROR
|
||||
if (c != '(')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var rawTextAux = rawText.Substring(i + 1);
|
||||
var buf = new StringBuilder();
|
||||
|
||||
for (int index = 0; index < rawTextAux.Length; index++)
|
||||
{
|
||||
char currentChar = rawTextAux[index];
|
||||
if (currentChar == ')')
|
||||
{
|
||||
return buf.ToString();
|
||||
}
|
||||
if (currentChar < '0' || currentChar > '9')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
buf.Append(currentChar);
|
||||
}
|
||||
return buf.ToString();
|
||||
}
|
||||
|
||||
private static String findValue(int i, String rawText)
|
||||
{
|
||||
var buf = new StringBuilder();
|
||||
var rawTextAux = rawText.Substring(i);
|
||||
|
||||
for (int index = 0; index < rawTextAux.Length; index++)
|
||||
{
|
||||
char c = rawTextAux[index];
|
||||
if (c == '(')
|
||||
{
|
||||
// We look for a new AI. If it doesn't exist (ERROR), we continue
|
||||
// with the iteration
|
||||
if (findAIvalue(index, rawTextAux) != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
buf.Append('(');
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.Append(c);
|
||||
}
|
||||
}
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
136
Others/zxing.core/zxing.core/client/result/GeoParsedResult.cs
Normal file
136
Others/zxing.core/zxing.core/client/result/GeoParsedResult.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes a geographic coordinate, with latitude, longitude and altitude.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class GeoParsedResult : ParsedResult
|
||||
{
|
||||
internal GeoParsedResult(double latitude, double longitude, double altitude, String query)
|
||||
: base(ParsedResultType.GEO)
|
||||
{
|
||||
Latitude = latitude;
|
||||
Longitude = longitude;
|
||||
Altitude = altitude;
|
||||
Query = query;
|
||||
GeoURI = getGeoURI();
|
||||
GoogleMapsURI = getGoogleMapsURI();
|
||||
displayResultValue = getDisplayResult();
|
||||
}
|
||||
|
||||
/// <returns> latitude in degrees
|
||||
/// </returns>
|
||||
public double Latitude { get; private set; }
|
||||
|
||||
/// <returns> longitude in degrees
|
||||
/// </returns>
|
||||
public double Longitude { get; private set; }
|
||||
|
||||
/// <returns> altitude in meters. If not specified, in the geo URI, returns 0.0
|
||||
/// </returns>
|
||||
public double Altitude { get; private set; }
|
||||
|
||||
/// <return> query string associated with geo URI or null if none exists</return>
|
||||
public String Query { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// the geo URI
|
||||
/// </summary>
|
||||
public String GeoURI { get; private set; }
|
||||
|
||||
/// <returns> a URI link to Google Maps which display the point on the Earth described
|
||||
/// by this instance, and sets the zoom level in a way that roughly reflects the
|
||||
/// altitude, if specified
|
||||
/// </returns>
|
||||
public String GoogleMapsURI { get; private set; }
|
||||
|
||||
private String getDisplayResult()
|
||||
{
|
||||
var result = new StringBuilder(20);
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Latitude);
|
||||
result.Append(", ");
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Longitude);
|
||||
if (Altitude > 0.0)
|
||||
{
|
||||
result.Append(", ");
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Altitude);
|
||||
result.Append('m');
|
||||
}
|
||||
if (Query != null)
|
||||
{
|
||||
result.Append(" (");
|
||||
result.Append(Query);
|
||||
result.Append(')');
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private String getGeoURI()
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
result.Append("geo:");
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Latitude);
|
||||
result.Append(',');
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Longitude);
|
||||
if (Altitude > 0)
|
||||
{
|
||||
result.Append(',');
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Altitude);
|
||||
}
|
||||
if (Query != null)
|
||||
{
|
||||
result.Append('?');
|
||||
result.Append(Query);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private String getGoogleMapsURI()
|
||||
{
|
||||
var result = new StringBuilder(50);
|
||||
result.Append("http://maps.google.com/?ll=");
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Latitude);
|
||||
result.Append(',');
|
||||
result.AppendFormat(CultureInfo.InvariantCulture, "{0:0.0###########}", Longitude);
|
||||
if (Altitude > 0.0f)
|
||||
{
|
||||
// Map altitude to zoom level, cleverly. Roughly, zoom level 19 is like a
|
||||
// view from 1000ft, 18 is like 2000ft, 17 like 4000ft, and so on.
|
||||
double altitudeInFeet = Altitude * 3.28;
|
||||
int altitudeInKFeet = (int)(altitudeInFeet / 1000.0);
|
||||
// No Math.log() available here, so compute log base 2 the old fashioned way
|
||||
// Here logBaseTwo will take on a value between 0 and 18 actually
|
||||
int logBaseTwo = 0;
|
||||
while (altitudeInKFeet > 1 && logBaseTwo < 18)
|
||||
{
|
||||
altitudeInKFeet >>= 1;
|
||||
logBaseTwo++;
|
||||
}
|
||||
int zoom = 19 - logBaseTwo;
|
||||
result.Append("&z=");
|
||||
result.Append(zoom);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
102
Others/zxing.core/zxing.core/client/result/GeoResultParser.cs
Normal file
102
Others/zxing.core/zxing.core/client/result/GeoResultParser.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary> Parses a "geo:" URI result, which specifies a location on the surface of
|
||||
/// the Earth as well as an optional altitude above the surface. See
|
||||
/// <a href="http://tools.ietf.org/html/draft-mayrhofer-geo-uri-00">
|
||||
/// http://tools.ietf.org/html/draft-mayrhofer-geo-uri-00</a>.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class GeoResultParser : ResultParser
|
||||
{
|
||||
private static readonly Regex GEO_URL_PATTERN = new Regex(@"\A(?:" + "geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?" + @")\z"
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
#else
|
||||
, RegexOptions.IgnoreCase);
|
||||
#endif
|
||||
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var matcher = GEO_URL_PATTERN.Match(rawText);
|
||||
if (!matcher.Success)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String query = matcher.Groups[4].Value;
|
||||
if (String.IsNullOrEmpty(query))
|
||||
query = null;
|
||||
|
||||
double latitude;
|
||||
double longitude;
|
||||
double altitude = 0.0;
|
||||
#if WindowsCE
|
||||
try { latitude = Double.Parse(matcher.Groups[1].Value, NumberStyles.Float, CultureInfo.InvariantCulture); }
|
||||
catch { return null; }
|
||||
#else
|
||||
if (!Double.TryParse(matcher.Groups[1].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out latitude))
|
||||
return null;
|
||||
#endif
|
||||
if (latitude > 90.0 || latitude < -90.0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
#if WindowsCE
|
||||
try { longitude = Double.Parse(matcher.Groups[2].Value, NumberStyles.Float, CultureInfo.InvariantCulture); }
|
||||
catch { return null; }
|
||||
#else
|
||||
if (!Double.TryParse(matcher.Groups[2].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out longitude))
|
||||
return null;
|
||||
#endif
|
||||
if (longitude > 180.0 || longitude < -180.0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!String.IsNullOrEmpty(matcher.Groups[3].Value))
|
||||
{
|
||||
#if WindowsCE
|
||||
try { altitude = Double.Parse(matcher.Groups[3].Value, NumberStyles.Float, CultureInfo.InvariantCulture); }
|
||||
catch { return null; }
|
||||
#else
|
||||
if (!Double.TryParse(matcher.Groups[3].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out altitude))
|
||||
return null;
|
||||
#endif
|
||||
if (altitude < 0.0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new GeoParsedResult(latitude, longitude, altitude, query);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes a product ISBN number.
|
||||
/// </summary>
|
||||
/// <author>jbreiden@google.com (Jeff Breidenbach)</author>
|
||||
public sealed class ISBNParsedResult : ParsedResult
|
||||
{
|
||||
internal ISBNParsedResult(String isbn)
|
||||
: base(ParsedResultType.ISBN)
|
||||
{
|
||||
ISBN = isbn;
|
||||
displayResultValue = isbn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the ISBN number
|
||||
/// </summary>
|
||||
public String ISBN { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary> Parses strings of digits that represent a ISBN.
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> jbreiden@google.com (Jeff Breidenbach)
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
public class ISBNResultParser : ResultParser
|
||||
{
|
||||
/// <summary>
|
||||
/// See <a href="http://www.bisg.org/isbn-13/for.dummies.html">ISBN-13 For Dummies</a>
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
/// <returns></returns>
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
BarcodeFormat format = result.BarcodeFormat;
|
||||
if (format != BarcodeFormat.EAN_13)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String rawText = result.Text;
|
||||
int length = rawText.Length;
|
||||
if (length != 13)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!rawText.StartsWith("978") && !rawText.StartsWith("979"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ISBNParsedResult(rawText);
|
||||
}
|
||||
}
|
||||
}
|
||||
114
Others/zxing.core/zxing.core/client/result/ParsedResult.cs
Normal file
114
Others/zxing.core/zxing.core/client/result/ParsedResult.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary> <p>Abstract class representing the result of decoding a barcode, as more than
|
||||
/// a String -- as some type of structured data. This might be a subclass which represents
|
||||
/// a URL, or an e-mail address. {@link ResultParser#parseResult(Result)} will turn a raw
|
||||
/// decoded string into the most appropriate type of structured representation.</p>
|
||||
///
|
||||
/// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
|
||||
/// on exception-based mechanisms during parsing.</p>
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public abstract class ParsedResult
|
||||
{
|
||||
/// <summary>
|
||||
/// user friendly value
|
||||
/// </summary>
|
||||
protected string displayResultValue;
|
||||
/// <summary>
|
||||
/// gets the type of the parsed result
|
||||
/// </summary>
|
||||
public virtual ParsedResultType Type { get; private set; }
|
||||
/// <summary>
|
||||
/// user friendly value
|
||||
/// </summary>
|
||||
public virtual String DisplayResult { get { return displayResultValue; } }
|
||||
/// <summary>
|
||||
/// constructor
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
protected ParsedResult(ParsedResultType type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
/// <summary>
|
||||
/// gets a user friendly value
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override String ToString()
|
||||
{
|
||||
return DisplayResult;
|
||||
}
|
||||
/// <summary>
|
||||
/// compare two objects
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as ParsedResult;
|
||||
if (other == null)
|
||||
return false;
|
||||
return other.Type.Equals(Type) && other.DisplayResult.Equals(DisplayResult);
|
||||
}
|
||||
/// <summary>
|
||||
/// gets the hashcode
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Type.GetHashCode() + DisplayResult.GetHashCode();
|
||||
}
|
||||
/// <summary>
|
||||
/// append to result if not null or empty
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="result"></param>
|
||||
public static void maybeAppend(String value, StringBuilder result)
|
||||
{
|
||||
if (String.IsNullOrEmpty(value))
|
||||
return;
|
||||
|
||||
// Don't add a newline before the first value
|
||||
if (result.Length > 0)
|
||||
{
|
||||
result.Append('\n');
|
||||
}
|
||||
result.Append(value);
|
||||
}
|
||||
/// <summary>
|
||||
/// append to result if not null or empty
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
/// <param name="result"></param>
|
||||
public static void maybeAppend(String[] values, StringBuilder result)
|
||||
{
|
||||
if (values != null)
|
||||
{
|
||||
foreach (String value in values)
|
||||
{
|
||||
maybeAppend(value, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the type of data encoded by a barcode -- from plain text, to a
|
||||
/// URI, to an e-mail address, etc.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public enum ParsedResultType
|
||||
{
|
||||
/// <summary>
|
||||
/// address book
|
||||
/// </summary>
|
||||
ADDRESSBOOK,
|
||||
/// <summary>
|
||||
/// email address
|
||||
/// </summary>
|
||||
EMAIL_ADDRESS,
|
||||
/// <summary>
|
||||
/// product
|
||||
/// </summary>
|
||||
PRODUCT,
|
||||
/// <summary>
|
||||
/// URI
|
||||
/// </summary>
|
||||
URI,
|
||||
/// <summary>
|
||||
/// Text
|
||||
/// </summary>
|
||||
TEXT,
|
||||
/// <summary>
|
||||
/// geo coordinates
|
||||
/// </summary>
|
||||
GEO,
|
||||
/// <summary>
|
||||
/// telefon
|
||||
/// </summary>
|
||||
TEL,
|
||||
/// <summary>
|
||||
/// sms
|
||||
/// </summary>
|
||||
SMS,
|
||||
/// <summary>
|
||||
/// calendar
|
||||
/// </summary>
|
||||
CALENDAR,
|
||||
/// <summary>
|
||||
/// wifi
|
||||
/// </summary>
|
||||
WIFI,
|
||||
/// <summary>
|
||||
/// ISBN
|
||||
/// </summary>
|
||||
ISBN,
|
||||
/// <summary>
|
||||
/// VIN
|
||||
/// </summary>
|
||||
VIN
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes a product by an identifier of some kind.
|
||||
/// </summary>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
public sealed class ProductParsedResult : ParsedResult
|
||||
{
|
||||
internal ProductParsedResult(String productID)
|
||||
: this(productID, productID)
|
||||
{
|
||||
}
|
||||
|
||||
internal ProductParsedResult(String productID, String normalizedProductID)
|
||||
: base(ParsedResultType.PRODUCT)
|
||||
{
|
||||
ProductID = productID;
|
||||
NormalizedProductID = normalizedProductID;
|
||||
displayResultValue = productID;
|
||||
}
|
||||
/// <summary>
|
||||
/// product id
|
||||
/// </summary>
|
||||
public String ProductID { get; private set; }
|
||||
/// <summary>
|
||||
/// normalized product id
|
||||
/// </summary>
|
||||
public String NormalizedProductID { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.OneD;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses strings of digits that represent a UPC code.
|
||||
/// </summary>
|
||||
/// <author>dswitkin@google.com (Daniel Switkin)</author>
|
||||
internal sealed class ProductResultParser : ResultParser
|
||||
{
|
||||
// Treat all UPC and EAN variants as UPCs, in the sense that they are all product barcodes.
|
||||
public override ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
BarcodeFormat format = result.BarcodeFormat;
|
||||
if (!(format == BarcodeFormat.UPC_A || format == BarcodeFormat.UPC_E ||
|
||||
format == BarcodeFormat.EAN_8 || format == BarcodeFormat.EAN_13))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Really neither of these should happen:
|
||||
String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isStringOfDigits(rawText, rawText.Length))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Not actually checking the checksum again here
|
||||
|
||||
String normalizedProductID;
|
||||
// Expand UPC-E for purposes of searching
|
||||
if (format == BarcodeFormat.UPC_E && rawText.Length == 8)
|
||||
{
|
||||
normalizedProductID = UPCEReader.convertUPCEtoUPCA(rawText);
|
||||
}
|
||||
else
|
||||
{
|
||||
normalizedProductID = rawText;
|
||||
}
|
||||
|
||||
return new ProductParsedResult(rawText, normalizedProductID);
|
||||
}
|
||||
}
|
||||
}
|
||||
408
Others/zxing.core/zxing.core/client/result/ResultParser.cs
Normal file
408
Others/zxing.core/zxing.core/client/result/ResultParser.cs
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* 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.RegularExpressions;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary> <p>Abstract class representing the result of decoding a barcode, as more than
|
||||
/// a String -- as some type of structured data. This might be a subclass which represents
|
||||
/// a URL, or an e-mail address. {@link #parseResult(com.google.zxing.Result)} will turn a raw
|
||||
/// decoded string into the most appropriate type of structured representation.</p>
|
||||
///
|
||||
/// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
|
||||
/// on exception-based mechanisms during parsing.</p>
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public abstract class ResultParser
|
||||
{
|
||||
private static readonly ResultParser[] PARSERS =
|
||||
{
|
||||
new BookmarkDoCoMoResultParser(),
|
||||
new AddressBookDoCoMoResultParser(),
|
||||
new EmailDoCoMoResultParser(),
|
||||
new AddressBookAUResultParser(),
|
||||
new VCardResultParser(),
|
||||
new BizcardResultParser(),
|
||||
new VEventResultParser(),
|
||||
new EmailAddressResultParser(),
|
||||
new SMTPResultParser(),
|
||||
new TelResultParser(),
|
||||
new SMSMMSResultParser(),
|
||||
new SMSTOMMSTOResultParser(),
|
||||
new GeoResultParser(),
|
||||
new WifiResultParser(),
|
||||
new URLTOResultParser(),
|
||||
new URIResultParser(),
|
||||
new ISBNResultParser(),
|
||||
new ProductResultParser(),
|
||||
new ExpandedProductResultParser(),
|
||||
new VINResultParser(),
|
||||
};
|
||||
|
||||
#if SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2
|
||||
private static readonly Regex DIGITS = new Regex(@"\A(?:" + "\\d+" + @")\z");
|
||||
private static readonly Regex AMPERSAND = new Regex("&");
|
||||
private static readonly Regex EQUALS = new Regex("=");
|
||||
#else
|
||||
private static readonly Regex DIGITS = new Regex(@"\A(?:" + "\\d+" + @")\z", RegexOptions.Compiled);
|
||||
private static readonly Regex AMPERSAND = new Regex("&", RegexOptions.Compiled);
|
||||
private static readonly Regex EQUALS = new Regex("=", RegexOptions.Compiled);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse the raw {@link Result}'s contents as a particular type
|
||||
/// of information (email, URL, etc.) and return a {@link ParsedResult} encapsulating
|
||||
/// the result of parsing.
|
||||
/// </summary>
|
||||
/// <param name="theResult">the raw <see cref="Result"/> to parse</param>
|
||||
/// <returns><see cref="ParsedResult" /> encapsulating the parsing result</returns>
|
||||
public abstract ParsedResult parse(ZXing.Result theResult);
|
||||
|
||||
/// <summary>
|
||||
/// Parses the result.
|
||||
/// </summary>
|
||||
/// <param name="theResult">The result.</param>
|
||||
/// <returns></returns>
|
||||
public static ParsedResult parseResult(ZXing.Result theResult)
|
||||
{
|
||||
foreach (var parser in PARSERS)
|
||||
{
|
||||
var result = parser.parse(theResult);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return new TextParsedResult(theResult.Text, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// append value to result, if not null
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="result"></param>
|
||||
protected static void maybeAppend(String value, System.Text.StringBuilder result)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
result.Append('\n');
|
||||
result.Append(value);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// append value to result, if not null
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="result"></param>
|
||||
protected static void maybeAppend(String[] value, System.Text.StringBuilder result)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
result.Append('\n');
|
||||
result.Append(value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// wrap, if not null
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
protected static String[] maybeWrap(String value)
|
||||
{
|
||||
return value == null ? null : new[] { value };
|
||||
}
|
||||
/// <summary>
|
||||
/// unescape backslash
|
||||
/// </summary>
|
||||
/// <param name="escaped"></param>
|
||||
/// <returns></returns>
|
||||
protected static String unescapeBackslash(String escaped)
|
||||
{
|
||||
if (escaped != null)
|
||||
{
|
||||
int backslash = escaped.IndexOf('\\');
|
||||
if (backslash >= 0)
|
||||
{
|
||||
int max = escaped.Length;
|
||||
var unescaped = new System.Text.StringBuilder(max - 1);
|
||||
unescaped.Append(escaped.ToCharArray(), 0, backslash);
|
||||
bool nextIsEscaped = false;
|
||||
for (int i = backslash; i < max; i++)
|
||||
{
|
||||
char c = escaped[i];
|
||||
if (nextIsEscaped || c != '\\')
|
||||
{
|
||||
unescaped.Append(c);
|
||||
nextIsEscaped = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextIsEscaped = true;
|
||||
}
|
||||
}
|
||||
return unescaped.ToString();
|
||||
}
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
/// <summary>
|
||||
/// parse hex digit
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <returns></returns>
|
||||
protected static int parseHexDigit(char c)
|
||||
{
|
||||
if (c >= 'a')
|
||||
{
|
||||
if (c <= 'f')
|
||||
{
|
||||
return 10 + (c - 'a');
|
||||
}
|
||||
}
|
||||
else if (c >= 'A')
|
||||
{
|
||||
if (c <= 'F')
|
||||
{
|
||||
return 10 + (c - 'A');
|
||||
}
|
||||
}
|
||||
else if (c >= '0')
|
||||
{
|
||||
if (c <= '9')
|
||||
{
|
||||
return c - '0';
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal static bool isStringOfDigits(String value, int length)
|
||||
{
|
||||
return value != null && length > 0 && length == value.Length && DIGITS.Match(value).Success;
|
||||
}
|
||||
|
||||
internal static bool isSubstringOfDigits(String value, int offset, int length)
|
||||
{
|
||||
if (value == null || length <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int max = offset + length;
|
||||
return value.Length >= max && DIGITS.Match(value, offset, length).Success;
|
||||
}
|
||||
|
||||
internal static IDictionary<string, string> parseNameValuePairs(String uri)
|
||||
{
|
||||
int paramStart = uri.IndexOf('?');
|
||||
if (paramStart < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var result = new Dictionary<String, String>(3);
|
||||
foreach (var keyValue in AMPERSAND.Split(uri.Substring(paramStart + 1)))
|
||||
{
|
||||
appendKeyValue(keyValue, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void appendKeyValue(String keyValue, IDictionary<String, String> result)
|
||||
{
|
||||
String[] keyValueTokens = EQUALS.Split(keyValue, 2);
|
||||
if (keyValueTokens.Length == 2)
|
||||
{
|
||||
String key = keyValueTokens[0];
|
||||
String value = keyValueTokens[1];
|
||||
try
|
||||
{
|
||||
//value = URLDecoder.decode(value, "UTF-8");
|
||||
value = urlDecode(value);
|
||||
result[key] = value;
|
||||
}
|
||||
catch (Exception uee)
|
||||
{
|
||||
throw new InvalidOperationException("url decoding failed", uee); // can't happen
|
||||
}
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static String[] matchPrefixedField(String prefix, String rawText, char endChar, bool trim)
|
||||
{
|
||||
IList<string> matches = null;
|
||||
int i = 0;
|
||||
int max = rawText.Length;
|
||||
while (i < max)
|
||||
{
|
||||
i = rawText.IndexOf(prefix, i);
|
||||
if (i < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i += prefix.Length; // Skip past this prefix we found to start
|
||||
int start = i; // Found the start of a match here
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
i = rawText.IndexOf(endChar, i);
|
||||
if (i < 0)
|
||||
{
|
||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||
i = rawText.Length;
|
||||
done = true;
|
||||
}
|
||||
else if (countPrecedingBackslashes(rawText, i) % 2 != 0)
|
||||
{
|
||||
// semicolon was escaped (odd count of preceding backslashes) so continue
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// found a match
|
||||
if (matches == null)
|
||||
{
|
||||
matches = new List<string>();
|
||||
}
|
||||
String element = unescapeBackslash(rawText.Substring(start, (i) - (start)));
|
||||
if (trim)
|
||||
{
|
||||
element = element.Trim();
|
||||
}
|
||||
if (!String.IsNullOrEmpty(element))
|
||||
{
|
||||
matches.Add(element);
|
||||
}
|
||||
i++;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matches == null || (matches.Count == 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return SupportClass.toStringArray(matches);
|
||||
}
|
||||
|
||||
private static int countPrecedingBackslashes(String s, int pos)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = pos - 1; i >= 0; i--)
|
||||
{
|
||||
if (s[i] == '\\')
|
||||
{
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
internal static String matchSinglePrefixedField(String prefix, String rawText, char endChar, bool trim)
|
||||
{
|
||||
String[] matches = matchPrefixedField(prefix, rawText, endChar, trim);
|
||||
return matches == null ? null : matches[0];
|
||||
}
|
||||
/// <summary>
|
||||
/// decodes url
|
||||
/// </summary>
|
||||
/// <param name="escaped"></param>
|
||||
/// <returns></returns>
|
||||
protected static String urlDecode(String escaped)
|
||||
{
|
||||
// Should we better use HttpUtility.UrlDecode?
|
||||
// Is HttpUtility.UrlDecode available for all platforms?
|
||||
// What about encoding like UTF8?
|
||||
|
||||
if (escaped == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
char[] escapedArray = escaped.ToCharArray();
|
||||
|
||||
int first = findFirstEscape(escapedArray);
|
||||
if (first < 0)
|
||||
{
|
||||
return escaped;
|
||||
}
|
||||
|
||||
int max = escapedArray.Length;
|
||||
// final length is at most 2 less than original due to at least 1 unescaping
|
||||
var unescaped = new System.Text.StringBuilder(max - 2);
|
||||
// Can append everything up to first escape character
|
||||
unescaped.Append(escapedArray, 0, first);
|
||||
|
||||
for (int i = first; i < max; i++)
|
||||
{
|
||||
char c = escapedArray[i];
|
||||
if (c == '+')
|
||||
{
|
||||
// + is translated directly into a space
|
||||
unescaped.Append(' ');
|
||||
}
|
||||
else if (c == '%')
|
||||
{
|
||||
// Are there even two more chars? if not we will just copy the escaped sequence and be done
|
||||
if (i >= max - 2)
|
||||
{
|
||||
unescaped.Append('%'); // append that % and move on
|
||||
}
|
||||
else
|
||||
{
|
||||
int firstDigitValue = parseHexDigit(escapedArray[++i]);
|
||||
int secondDigitValue = parseHexDigit(escapedArray[++i]);
|
||||
if (firstDigitValue < 0 || secondDigitValue < 0)
|
||||
{
|
||||
// bad digit, just move on
|
||||
unescaped.Append('%');
|
||||
unescaped.Append(escapedArray[i - 1]);
|
||||
unescaped.Append(escapedArray[i]);
|
||||
}
|
||||
unescaped.Append((char)((firstDigitValue << 4) + secondDigitValue));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unescaped.Append(c);
|
||||
}
|
||||
}
|
||||
return unescaped.ToString();
|
||||
}
|
||||
|
||||
private static int findFirstEscape(char[] escapedArray)
|
||||
{
|
||||
int max = escapedArray.Length;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
char c = escapedArray[i];
|
||||
if (c == '+' || c == '%')
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
118
Others/zxing.core/zxing.core/client/result/SMSMMSResultParser.cs
Normal file
118
Others/zxing.core/zxing.core/client/result/SMSMMSResultParser.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2008 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary> <p>Parses an "sms:" URI result, which specifies a number to SMS and optional
|
||||
/// "via" number. See <a href="http://gbiv.com/protocols/uri/drafts/draft-antti-gsm-sms-url-04.txt">
|
||||
/// the IETF draft</a> on this.</p>
|
||||
///
|
||||
/// <p>This actually also parses URIs starting with "mms:", "smsto:", "mmsto:", "SMSTO:", and
|
||||
/// "MMSTO:", and treats them all the same way, and effectively converts them to an "sms:" URI
|
||||
/// for purposes of forwarding to the platform.</p>
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class SMSMMSResultParser : ResultParser
|
||||
{
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null ||
|
||||
!(rawText.StartsWith("sms:") || rawText.StartsWith("SMS:") ||
|
||||
rawText.StartsWith("mms:") || rawText.StartsWith("MMS:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check up front if this is a URI syntax string with query arguments
|
||||
var nameValuePairs = parseNameValuePairs(rawText);
|
||||
String subject = null;
|
||||
String body = null;
|
||||
var querySyntax = false;
|
||||
if (nameValuePairs != null && nameValuePairs.Count != 0)
|
||||
{
|
||||
subject = nameValuePairs["subject"];
|
||||
body = nameValuePairs["body"];
|
||||
querySyntax = true;
|
||||
}
|
||||
|
||||
// Drop sms, query portion
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
var queryStart = rawText.IndexOf('?', 4);
|
||||
String smsURIWithoutQuery;
|
||||
// If it's not query syntax, the question mark is part of the subject or message
|
||||
if (queryStart < 0 || !querySyntax)
|
||||
{
|
||||
smsURIWithoutQuery = rawText.Substring(4);
|
||||
}
|
||||
else
|
||||
{
|
||||
smsURIWithoutQuery = rawText.Substring(4, (queryStart) - (4));
|
||||
}
|
||||
|
||||
int lastComma = -1;
|
||||
int comma;
|
||||
var numbers = new List<String>(1);
|
||||
var vias = new List<String>(1);
|
||||
while ((comma = smsURIWithoutQuery.IndexOf(',', lastComma + 1)) > lastComma)
|
||||
{
|
||||
String numberPart = smsURIWithoutQuery.Substring(lastComma + 1, comma);
|
||||
addNumberVia(numbers, vias, numberPart);
|
||||
lastComma = comma;
|
||||
}
|
||||
addNumberVia(numbers, vias, smsURIWithoutQuery.Substring(lastComma + 1));
|
||||
|
||||
return new SMSParsedResult(SupportClass.toStringArray(numbers),
|
||||
SupportClass.toStringArray(vias),
|
||||
subject,
|
||||
body);
|
||||
}
|
||||
|
||||
private static void addNumberVia(ICollection<String> numbers,
|
||||
ICollection<String> vias,
|
||||
String numberPart)
|
||||
{
|
||||
int numberEnd = numberPart.IndexOf(';');
|
||||
if (numberEnd < 0)
|
||||
{
|
||||
numbers.Add(numberPart);
|
||||
vias.Add(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
numbers.Add(numberPart.Substring(0, numberEnd));
|
||||
String maybeVia = numberPart.Substring(numberEnd + 1);
|
||||
String via;
|
||||
if (maybeVia.StartsWith("via="))
|
||||
{
|
||||
via = maybeVia.Substring(4);
|
||||
}
|
||||
else
|
||||
{
|
||||
via = null;
|
||||
}
|
||||
vias.Add(via);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
134
Others/zxing.core/zxing.core/client/result/SMSParsedResult.cs
Normal file
134
Others/zxing.core/zxing.core/client/result/SMSParsedResult.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes an SMS message, including recipients, subject and body text.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class SMSParsedResult : ParsedResult
|
||||
{
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <param name="via"></param>
|
||||
/// <param name="subject"></param>
|
||||
/// <param name="body"></param>
|
||||
public SMSParsedResult(String number,
|
||||
String via,
|
||||
String subject,
|
||||
String body)
|
||||
: this(new[] { number }, new[] { via }, subject, body)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="numbers"></param>
|
||||
/// <param name="vias"></param>
|
||||
/// <param name="subject"></param>
|
||||
/// <param name="body"></param>
|
||||
public SMSParsedResult(String[] numbers,
|
||||
String[] vias,
|
||||
String subject,
|
||||
String body)
|
||||
: base(ParsedResultType.SMS)
|
||||
{
|
||||
Numbers = numbers;
|
||||
Vias = vias;
|
||||
Subject = subject;
|
||||
Body = body;
|
||||
SMSURI = getSMSURI();
|
||||
|
||||
var result = new StringBuilder(100);
|
||||
maybeAppend(Numbers, result);
|
||||
maybeAppend(Subject, result);
|
||||
maybeAppend(Body, result);
|
||||
displayResultValue = result.ToString();
|
||||
}
|
||||
|
||||
private String getSMSURI()
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
result.Append("sms:");
|
||||
bool first = true;
|
||||
for (int i = 0; i < Numbers.Length; i++)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Append(',');
|
||||
}
|
||||
result.Append(Numbers[i]);
|
||||
if (Vias != null && Vias[i] != null)
|
||||
{
|
||||
result.Append(";via=");
|
||||
result.Append(Vias[i]);
|
||||
}
|
||||
}
|
||||
bool hasBody = Body != null;
|
||||
bool hasSubject = Subject != null;
|
||||
if (hasBody || hasSubject)
|
||||
{
|
||||
result.Append('?');
|
||||
if (hasBody)
|
||||
{
|
||||
result.Append("body=");
|
||||
result.Append(Body);
|
||||
}
|
||||
if (hasSubject)
|
||||
{
|
||||
if (hasBody)
|
||||
{
|
||||
result.Append('&');
|
||||
}
|
||||
result.Append("subject=");
|
||||
result.Append(Subject);
|
||||
}
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// numbers
|
||||
/// </summary>
|
||||
public String[] Numbers { get; private set; }
|
||||
/// <summary>
|
||||
/// vias
|
||||
/// </summary>
|
||||
public String[] Vias { get; private set; }
|
||||
/// <summary>
|
||||
/// subject
|
||||
/// </summary>
|
||||
public String Subject { get; private set; }
|
||||
/// <summary>
|
||||
/// body
|
||||
/// </summary>
|
||||
public String Body { get; private set; }
|
||||
/// <summary>
|
||||
/// sms uri
|
||||
/// </summary>
|
||||
public String SMSURI { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// <p>Parses an "smsto:" URI result, whose format is not standardized but appears to be like:
|
||||
/// {@code smsto:number(:body)}.</p>
|
||||
/// <p>This actually also parses URIs starting with "smsto:", "mmsto:", "SMSTO:", and
|
||||
/// "MMSTO:", and treats them all the same way, and effectively converts them to an "sms:" URI
|
||||
/// for purposes of forwarding to the platform.</p>
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public class SMSTOMMSTOResultParser : ResultParser
|
||||
{
|
||||
/// <summary>
|
||||
/// attempt to parse the raw result to the specific type
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public override ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (!(rawText.StartsWith("smsto:") || rawText.StartsWith("SMSTO:") ||
|
||||
rawText.StartsWith("mmsto:") || rawText.StartsWith("MMSTO:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Thanks to dominik.wild for suggesting this enhancement to support
|
||||
// smsto:number:body URIs
|
||||
String number = rawText.Substring(6);
|
||||
String body = null;
|
||||
int bodyStart = number.IndexOf(':');
|
||||
if (bodyStart >= 0)
|
||||
{
|
||||
body = number.Substring(bodyStart + 1);
|
||||
number = number.Substring(0, bodyStart);
|
||||
}
|
||||
return new SMSParsedResult(number, null, null, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// <p>Parses an "smtp:" URI result, whose format is not standardized but appears to be like:
|
||||
/// <code>smtp[:subject[:body]]}</code>.</p>
|
||||
/// <p>See http://code.google.com/p/zxing/issues/detail?id=536</p>
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public class SMTPResultParser : ResultParser
|
||||
{
|
||||
/// <summary>
|
||||
/// attempt to parse the raw result to the specific type
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
public override ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (!(rawText.StartsWith("smtp:") || rawText.StartsWith("SMTP:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String emailAddress = rawText.Substring(5);
|
||||
String subject = null;
|
||||
String body = null;
|
||||
int colon = emailAddress.IndexOf(':');
|
||||
if (colon >= 0)
|
||||
{
|
||||
subject = emailAddress.Substring(colon + 1);
|
||||
emailAddress = emailAddress.Substring(0, colon);
|
||||
colon = subject.IndexOf(':');
|
||||
if (colon >= 0)
|
||||
{
|
||||
body = subject.Substring(colon + 1);
|
||||
subject = subject.Substring(0, colon);
|
||||
}
|
||||
}
|
||||
return new EmailAddressParsedResult(new[] { emailAddress },
|
||||
null,
|
||||
null,
|
||||
subject,
|
||||
body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a parsed result that encodes a telephone number.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class TelParsedResult : ParsedResult
|
||||
{
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <param name="telURI"></param>
|
||||
/// <param name="title"></param>
|
||||
public TelParsedResult(String number, String telURI, String title)
|
||||
: base(ParsedResultType.TEL)
|
||||
{
|
||||
Number = number;
|
||||
TelURI = telURI;
|
||||
Title = title;
|
||||
|
||||
var result = new System.Text.StringBuilder(20);
|
||||
maybeAppend(number, result);
|
||||
maybeAppend(title, result);
|
||||
displayResultValue = result.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// number
|
||||
/// </summary>
|
||||
public String Number { get; private set; }
|
||||
/// <summary>
|
||||
/// URI
|
||||
/// </summary>
|
||||
public String TelURI { get; private set; }
|
||||
/// <summary>
|
||||
/// title
|
||||
/// </summary>
|
||||
public String Title { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses a "tel:" URI result, which specifies a phone number.
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class TelResultParser : ResultParser
|
||||
{
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null ||
|
||||
(!rawText.StartsWith("tel:") && !rawText.StartsWith("TEL:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Normalize "TEL:" to "tel:"
|
||||
String telURI = rawText.StartsWith("TEL:") ? "tel:" + rawText.Substring(4) : rawText;
|
||||
// Drop tel, query portion
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int queryStart = rawText.IndexOf('?', 4);
|
||||
String number = queryStart < 0 ? rawText.Substring(4) : rawText.Substring(4, (queryStart) - (4));
|
||||
return new TelParsedResult(number, telURI, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple result type encapsulating a string that has no further interpretation.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class TextParsedResult : ParsedResult
|
||||
{
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="language"></param>
|
||||
public TextParsedResult(String text, String language)
|
||||
: base(ParsedResultType.TEXT)
|
||||
{
|
||||
Text = text;
|
||||
Language = language;
|
||||
displayResultValue = text;
|
||||
}
|
||||
/// <summary>
|
||||
/// text
|
||||
/// </summary>
|
||||
public String Text { get; private set; }
|
||||
/// <summary>
|
||||
/// language
|
||||
/// </summary>
|
||||
public String Language { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple result type encapsulating a URI that has no further interpretation.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
public sealed class URIParsedResult : ParsedResult
|
||||
{
|
||||
/// <summary>
|
||||
/// URI
|
||||
/// </summary>
|
||||
public String URI { get; private set; }
|
||||
/// <summary>
|
||||
/// title
|
||||
/// </summary>
|
||||
public String Title { get; private set; }
|
||||
|
||||
/// <returns> true if the URI contains suspicious patterns that may suggest it intends to
|
||||
/// mislead the user about its true nature. At the moment this looks for the presence
|
||||
/// of user/password syntax in the host/authority portion of a URI which may be used
|
||||
/// in attempts to make the URI's host appear to be other than it is. Example:
|
||||
/// http://yourbank.com@phisher.com This URI connects to phisher.com but may appear
|
||||
/// to connect to yourbank.com at first glance.
|
||||
/// </returns>
|
||||
[Obsolete("deprecated, see {@link URIResultParser#isPossiblyMaliciousURI(String)")]
|
||||
public bool PossiblyMaliciousURI { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// initializing constructor
|
||||
/// </summary>
|
||||
/// <param name="uri"></param>
|
||||
/// <param name="title"></param>
|
||||
public URIParsedResult(String uri, String title)
|
||||
: base(ParsedResultType.URI)
|
||||
{
|
||||
URI = massageURI(uri);
|
||||
Title = title;
|
||||
PossiblyMaliciousURI = URIResultParser.isPossiblyMaliciousURI(uri);
|
||||
|
||||
var result = new System.Text.StringBuilder(30);
|
||||
maybeAppend(Title, result);
|
||||
maybeAppend(URI, result);
|
||||
displayResultValue = result.ToString();
|
||||
}
|
||||
|
||||
/// <summary> Transforms a string that represents a URI into something more proper, by adding or canonicalizing
|
||||
/// the protocol.
|
||||
/// </summary>
|
||||
private static String massageURI(String uri)
|
||||
{
|
||||
int protocolEnd = uri.IndexOf(':');
|
||||
if (protocolEnd < 0 || isColonFollowedByPortNumber(uri, protocolEnd))
|
||||
{
|
||||
// No protocol, or found a colon, but it looks like it is after the host, so the protocol is still missing,
|
||||
// so assume http
|
||||
uri = "http://" + uri;
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
private static bool isColonFollowedByPortNumber(String uri, int protocolEnd)
|
||||
{
|
||||
int start = protocolEnd + 1;
|
||||
int nextSlash = uri.IndexOf('/', start);
|
||||
if (nextSlash < 0)
|
||||
{
|
||||
nextSlash = uri.Length;
|
||||
}
|
||||
return ResultParser.isSubstringOfDigits(uri, start, nextSlash - start);
|
||||
}
|
||||
}
|
||||
}
|
||||
105
Others/zxing.core/zxing.core/client/result/URIResultParser.cs
Normal file
105
Others/zxing.core/zxing.core/client/result/URIResultParser.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.RegularExpressions;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to parse results that are a URI of some kind.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
sealed class URIResultParser : ResultParser
|
||||
{
|
||||
private static readonly Regex ALLOWED_URI_CHARS_PATTERN = new Regex("^[-._~:/?#\\[\\]@!$&'()*+,;=%A-Za-z0-9]+$"
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
private static readonly Regex USER_IN_HOST = new Regex(":/*([^/@]+)@[^/]+"
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
|
||||
// See http://www.ietf.org/rfc/rfc2396.txt
|
||||
private static readonly Regex URL_WITH_PROTOCOL_PATTERN = new Regex("[a-zA-Z][a-zA-Z0-9+-.]+:"
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
private static readonly Regex URL_WITHOUT_PROTOCOL_PATTERN = new Regex(
|
||||
"([a-zA-Z0-9\\-]+\\.){1,6}[a-zA-Z]{2,}" + // host name elements
|
||||
"(:\\d{1,5})?" + // maybe port
|
||||
"(/|\\?|$)" // query, path or nothing
|
||||
#if !(SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2)
|
||||
, RegexOptions.Compiled);
|
||||
#else
|
||||
);
|
||||
#endif
|
||||
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
// We specifically handle the odd "URL" scheme here for simplicity and add "URI" for fun
|
||||
// Assume anything starting this way really means to be a URI
|
||||
if (rawText.StartsWith("URL:") || rawText.StartsWith("URI:"))
|
||||
{
|
||||
return new URIParsedResult(rawText.Substring(4).Trim(), null);
|
||||
}
|
||||
rawText = rawText.Trim();
|
||||
if (!isBasicallyValidURI(rawText) || isPossiblyMaliciousURI(rawText))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new URIParsedResult(rawText, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the URI contains suspicious patterns that may suggest it intends to
|
||||
* mislead the user about its true nature. At the moment this looks for the presence
|
||||
* of user/password syntax in the host/authority portion of a URI which may be used
|
||||
* in attempts to make the URI's host appear to be other than it is. Example:
|
||||
* http://yourbank.com@phisher.com This URI connects to phisher.com but may appear
|
||||
* to connect to yourbank.com at first glance.
|
||||
*/
|
||||
internal static bool isPossiblyMaliciousURI(String uri)
|
||||
{
|
||||
return !ALLOWED_URI_CHARS_PATTERN.Match(uri).Success || USER_IN_HOST.Match(uri).Success;
|
||||
}
|
||||
|
||||
internal static bool isBasicallyValidURI(String uri)
|
||||
{
|
||||
if (uri.IndexOf(" ") >= 0)
|
||||
{
|
||||
// Quick hack check for a common case
|
||||
return false;
|
||||
}
|
||||
var m = URL_WITH_PROTOCOL_PATTERN.Match(uri);
|
||||
if (m.Success && m.Index == 0)
|
||||
{
|
||||
// match at start only
|
||||
return true;
|
||||
}
|
||||
m = URL_WITHOUT_PROTOCOL_PATTERN.Match(uri);
|
||||
return m.Success && m.Index == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.Client.Result
|
||||
{
|
||||
/// <summary> Parses the "URLTO" result format, which is of the form "URLTO:[title]:[url]".
|
||||
/// This seems to be used sometimes, but I am not able to find documentation
|
||||
/// on its origin or official format?
|
||||
///
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class URLTOResultParser : ResultParser
|
||||
{
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
var rawText = result.Text;
|
||||
if (rawText == null ||
|
||||
(!rawText.StartsWith("urlto:") && !rawText.StartsWith("URLTO:")))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
|
||||
int titleEnd = rawText.IndexOf(':', 6);
|
||||
if (titleEnd < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var title = titleEnd <= 6 ? null : rawText.Substring(6, (titleEnd) - (6));
|
||||
var uri = rawText.Substring(titleEnd + 1);
|
||||
return new URIParsedResult(uri, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
490
Others/zxing.core/zxing.core/client/result/VCardResultParser.cs
Normal file
490
Others/zxing.core/zxing.core/client/result/VCardResultParser.cs
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* 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.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Parses contact information formatted according to the VCard (2.1) format. This is not a complete
|
||||
/// implementation but should parse information as commonly encoded in 2D barcodes.
|
||||
/// </summary>
|
||||
/// <author>Sean Owen</author>
|
||||
sealed class VCardResultParser : ResultParser
|
||||
{
|
||||
#if SILVERLIGHT4 || SILVERLIGHT5 || NETFX_CORE || PORTABLE || UNITY || NETSTANDARD1_0 || NETSTANDARD1_1 || NETSTANDARD1_2
|
||||
private static readonly Regex BEGIN_VCARD = new Regex("BEGIN:VCARD", RegexOptions.IgnoreCase);
|
||||
private static readonly Regex VCARD_LIKE_DATE = new Regex(@"\A(?:" + "\\d{4}-?\\d{2}-?\\d{2}" + @")\z");
|
||||
private static readonly Regex CR_LF_SPACE_TAB = new Regex("\r\n[ \t]");
|
||||
private static readonly Regex NEWLINE_ESCAPE = new Regex("\\\\[nN]");
|
||||
private static readonly Regex VCARD_ESCAPES = new Regex("\\\\([,;\\\\])");
|
||||
private static readonly Regex EQUALS = new Regex("=");
|
||||
private static readonly Regex SEMICOLON = new Regex(";");
|
||||
private static readonly Regex UNESCAPED_SEMICOLONS = new Regex("(?<!\\\\);+");
|
||||
private static readonly Regex COMMA = new Regex(",");
|
||||
private static readonly Regex SEMICOLON_OR_COMMA = new Regex("[;,]");
|
||||
#else
|
||||
private static readonly Regex BEGIN_VCARD = new Regex("BEGIN:VCARD", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
private static readonly Regex VCARD_LIKE_DATE = new Regex(@"\A(?:" + "\\d{4}-?\\d{2}-?\\d{2}" + @")\z", RegexOptions.Compiled);
|
||||
private static readonly Regex CR_LF_SPACE_TAB = new Regex("\r\n[ \t]", RegexOptions.Compiled);
|
||||
private static readonly Regex NEWLINE_ESCAPE = new Regex("\\\\[nN]", RegexOptions.Compiled);
|
||||
private static readonly Regex VCARD_ESCAPES = new Regex("\\\\([,;\\\\])", RegexOptions.Compiled);
|
||||
private static readonly Regex EQUALS = new Regex("=", RegexOptions.Compiled);
|
||||
private static readonly Regex SEMICOLON = new Regex(";", RegexOptions.Compiled);
|
||||
private static readonly Regex UNESCAPED_SEMICOLONS = new Regex("(?<!\\\\);+", RegexOptions.Compiled);
|
||||
private static readonly Regex COMMA = new Regex(",", RegexOptions.Compiled);
|
||||
private static readonly Regex SEMICOLON_OR_COMMA = new Regex("[;,]", RegexOptions.Compiled);
|
||||
#endif
|
||||
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
// Although we should insist on the raw text ending with "END:VCARD", there's no reason
|
||||
// to throw out everything else we parsed just because this was omitted. In fact, Eclair
|
||||
// is doing just that, and we can't parse its contacts without this leniency.
|
||||
String rawText = result.Text;
|
||||
var m = BEGIN_VCARD.Match(rawText);
|
||||
if (!m.Success || m.Index != 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<List<String>> names = matchVCardPrefixedField("FN", rawText, true, false);
|
||||
if (names == null)
|
||||
{
|
||||
// If no display names found, look for regular name fields and format them
|
||||
names = matchVCardPrefixedField("N", rawText, true, false);
|
||||
formatNames(names);
|
||||
}
|
||||
List<String> nicknameString = matchSingleVCardPrefixedField("NICKNAME", rawText, true, false);
|
||||
String[] nicknames = nicknameString == null ? null : COMMA.Split(nicknameString[0]);
|
||||
List<List<String>> phoneNumbers = matchVCardPrefixedField("TEL", rawText, true, false);
|
||||
List<List<String>> emails = matchVCardPrefixedField("EMAIL", rawText, true, false);
|
||||
List<String> note = matchSingleVCardPrefixedField("NOTE", rawText, false, false);
|
||||
List<List<String>> addresses = matchVCardPrefixedField("ADR", rawText, true, true);
|
||||
List<String> org = matchSingleVCardPrefixedField("ORG", rawText, true, true);
|
||||
List<String> birthday = matchSingleVCardPrefixedField("BDAY", rawText, true, false);
|
||||
if (birthday != null && !isLikeVCardDate(birthday[0]))
|
||||
{
|
||||
birthday = null;
|
||||
}
|
||||
List<String> title = matchSingleVCardPrefixedField("TITLE", rawText, true, false);
|
||||
List<List<String>> urls = matchVCardPrefixedField("URL", rawText, true, false);
|
||||
List<String> instantMessenger = matchSingleVCardPrefixedField("IMPP", rawText, true, false);
|
||||
List<String> geoString = matchSingleVCardPrefixedField("GEO", rawText, true, false);
|
||||
String[] geo = geoString == null ? null : SEMICOLON_OR_COMMA.Split(geoString[0]);
|
||||
if (geo != null && geo.Length != 2)
|
||||
{
|
||||
geo = null;
|
||||
}
|
||||
return new AddressBookParsedResult(toPrimaryValues(names),
|
||||
nicknames,
|
||||
null,
|
||||
toPrimaryValues(phoneNumbers),
|
||||
toTypes(phoneNumbers),
|
||||
toPrimaryValues(emails),
|
||||
toTypes(emails),
|
||||
toPrimaryValue(instantMessenger),
|
||||
toPrimaryValue(note),
|
||||
toPrimaryValues(addresses),
|
||||
toTypes(addresses),
|
||||
toPrimaryValue(org),
|
||||
toPrimaryValue(birthday),
|
||||
toPrimaryValue(title),
|
||||
toPrimaryValues(urls),
|
||||
geo);
|
||||
}
|
||||
|
||||
public static List<List<String>> matchVCardPrefixedField(String prefix,
|
||||
String rawText,
|
||||
bool trim,
|
||||
bool parseFieldDivider)
|
||||
{
|
||||
List<List<String>> matches = null;
|
||||
int i = 0;
|
||||
int max = rawText.Length;
|
||||
|
||||
while (i < max)
|
||||
{
|
||||
// At start or after newline, match prefix, followed by optional metadata
|
||||
// (led by ;) ultimately ending in colon
|
||||
var matcher = new Regex("(?:^|\n)" + prefix + "(?:;([^:]*))?:", RegexOptions.IgnoreCase);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
i--; // Find from i-1 not i since looking at the preceding character
|
||||
}
|
||||
var match = matcher.Match(rawText, i);
|
||||
if (!match.Success)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i = match.Index + match.Length;
|
||||
|
||||
String metadataString = match.Groups[1].Value; // group 1 = metadata substring
|
||||
List<String> metadata = null;
|
||||
bool quotedPrintable = false;
|
||||
String quotedPrintableCharset = null;
|
||||
String valueType = null;
|
||||
if (metadataString != null)
|
||||
{
|
||||
foreach (String metadatum in SEMICOLON.Split(metadataString))
|
||||
{
|
||||
if (metadata == null)
|
||||
{
|
||||
metadata = new List<String>(1);
|
||||
}
|
||||
metadata.Add(metadatum);
|
||||
String[] metadatumTokens = EQUALS.Split(metadatum, 2);
|
||||
if (metadatumTokens.Length > 1)
|
||||
{
|
||||
String key = metadatumTokens[0];
|
||||
String value = metadatumTokens[1];
|
||||
if (String.Compare("ENCODING", key, StringComparison.OrdinalIgnoreCase) == 0 &&
|
||||
String.Compare("QUOTED-PRINTABLE", value, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
quotedPrintable = true;
|
||||
}
|
||||
else if (String.Compare("CHARSET", key, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
quotedPrintableCharset = value;
|
||||
}
|
||||
else if (String.Compare("VALUE", key, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
valueType = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int matchStart = i; // Found the start of a match here
|
||||
|
||||
while ((i = rawText.IndexOf('\n', i)) >= 0)
|
||||
{
|
||||
// Really, end in \r\n
|
||||
if (i < rawText.Length - 1 && // But if followed by tab or space,
|
||||
(rawText[i + 1] == ' ' || // this is only a continuation
|
||||
rawText[i + 1] == '\t'))
|
||||
{
|
||||
i += 2; // Skip \n and continutation whitespace
|
||||
}
|
||||
else if (quotedPrintable && // If preceded by = in quoted printable
|
||||
((i >= 1 && rawText[i - 1] == '=') || // this is a continuation
|
||||
(i >= 2 && rawText[i - 2] == '=')))
|
||||
{
|
||||
i++; // Skip \n
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||
i = max;
|
||||
}
|
||||
else if (i > matchStart)
|
||||
{
|
||||
// found a match
|
||||
if (matches == null)
|
||||
{
|
||||
matches = new List<List<String>>(1); // lazy init
|
||||
}
|
||||
if (i >= 1 && rawText[i - 1] == '\r')
|
||||
{
|
||||
i--; // Back up over \r, which really should be there
|
||||
}
|
||||
String element = rawText.Substring(matchStart, i - matchStart);
|
||||
if (trim)
|
||||
{
|
||||
element = element.Trim();
|
||||
}
|
||||
if (quotedPrintable)
|
||||
{
|
||||
element = decodeQuotedPrintable(element, quotedPrintableCharset);
|
||||
if (parseFieldDivider)
|
||||
{
|
||||
element = UNESCAPED_SEMICOLONS.Replace(element, "\n").Trim();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parseFieldDivider)
|
||||
{
|
||||
element = UNESCAPED_SEMICOLONS.Replace(element, "\n").Trim();
|
||||
}
|
||||
element = CR_LF_SPACE_TAB.Replace(element, "");
|
||||
element = NEWLINE_ESCAPE.Replace(element, "\n");
|
||||
element = VCARD_ESCAPES.Replace(element, "$1");
|
||||
}
|
||||
// Only handle VALUE=uri specially
|
||||
if ("uri".Equals(valueType))
|
||||
{
|
||||
// Don't actually support dereferencing URIs, but use scheme-specific part not URI
|
||||
// as value, to support tel: and mailto:
|
||||
try
|
||||
{
|
||||
Uri uri;
|
||||
if (Uri.TryCreate(element, UriKind.RelativeOrAbsolute, out uri))
|
||||
{
|
||||
element = uri.AbsoluteUri.Replace(uri.Scheme + ':', "");
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (metadata == null)
|
||||
{
|
||||
var matched = new List<String>(1);
|
||||
matched.Add(element);
|
||||
matches.Add(matched);
|
||||
}
|
||||
else
|
||||
{
|
||||
metadata.Insert(0, element);
|
||||
matches.Add(metadata);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
private static String decodeQuotedPrintable(String value, String charset)
|
||||
{
|
||||
int length = value.Length;
|
||||
var result = new StringBuilder(length);
|
||||
var fragmentBuffer = new MemoryStream();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
char c = value[i];
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
case '=':
|
||||
if (i < length - 2)
|
||||
{
|
||||
char nextChar = value[i + 1];
|
||||
if (nextChar == '\r' || nextChar == '\n')
|
||||
{
|
||||
// Ignore, it's just a continuation symbol
|
||||
}
|
||||
else
|
||||
{
|
||||
char nextNextChar = value[i + 2];
|
||||
int firstDigit = parseHexDigit(nextChar);
|
||||
int secondDigit = parseHexDigit(nextNextChar);
|
||||
if (firstDigit >= 0 && secondDigit >= 0)
|
||||
{
|
||||
fragmentBuffer.WriteByte((byte)((firstDigit << 4) | secondDigit));
|
||||
} // else ignore it, assume it was incorrectly encoded
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
maybeAppendFragment(fragmentBuffer, charset, result);
|
||||
result.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
maybeAppendFragment(fragmentBuffer, charset, result);
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private static void maybeAppendFragment(MemoryStream fragmentBuffer,
|
||||
String charset,
|
||||
StringBuilder result)
|
||||
{
|
||||
if (fragmentBuffer.Length > 0)
|
||||
{
|
||||
byte[] fragmentBytes = fragmentBuffer.ToArray();
|
||||
String fragment;
|
||||
if (charset == null)
|
||||
{
|
||||
#if WindowsCE
|
||||
fragment = Encoding.Default.GetString(fragmentBytes, 0, fragmentBytes.Length);
|
||||
#else
|
||||
fragment = Encoding.UTF8.GetString(fragmentBytes, 0, fragmentBytes.Length);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
fragment = Encoding.GetEncoding(charset).GetString(fragmentBytes, 0, fragmentBytes.Length);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
#if WindowsCE
|
||||
// WindowsCE doesn't support all encodings. But it is device depended.
|
||||
// So we try here the some different ones
|
||||
if (charset == "ISO-8859-1")
|
||||
{
|
||||
fragment = Encoding.GetEncoding(1252).GetString(fragmentBytes, 0, fragmentBytes.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
fragment = Encoding.Default.GetString(fragmentBytes, 0, fragmentBytes.Length);
|
||||
}
|
||||
fragment = Encoding.Default.GetString(fragmentBytes, 0, fragmentBytes.Length);
|
||||
#else
|
||||
fragment = Encoding.UTF8.GetString(fragmentBytes, 0, fragmentBytes.Length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
fragmentBuffer.Seek(0, SeekOrigin.Begin);
|
||||
fragmentBuffer.SetLength(0);
|
||||
result.Append(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
internal static List<String> matchSingleVCardPrefixedField(String prefix,
|
||||
String rawText,
|
||||
bool trim,
|
||||
bool parseFieldDivider)
|
||||
{
|
||||
List<List<String>> values = matchVCardPrefixedField(prefix, rawText, trim, parseFieldDivider);
|
||||
return values == null || values.Count == 0 ? null : values[0];
|
||||
}
|
||||
|
||||
private static String toPrimaryValue(List<String> list)
|
||||
{
|
||||
return list == null || list.Count == 0 ? null : list[0];
|
||||
}
|
||||
|
||||
private static String[] toPrimaryValues(ICollection<List<String>> lists)
|
||||
{
|
||||
if (lists == null || lists.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var result = new List<String>(lists.Count);
|
||||
foreach (var list in lists)
|
||||
{
|
||||
String value = list[0];
|
||||
if (!String.IsNullOrEmpty(value))
|
||||
{
|
||||
result.Add(value);
|
||||
}
|
||||
}
|
||||
return SupportClass.toStringArray(result);
|
||||
}
|
||||
|
||||
private static String[] toTypes(ICollection<List<String>> lists)
|
||||
{
|
||||
if (lists == null || lists.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<String> result = new List<String>(lists.Count);
|
||||
foreach (var list in lists)
|
||||
{
|
||||
String value = list[0];
|
||||
if (!String.IsNullOrEmpty(value))
|
||||
{
|
||||
String type = null;
|
||||
for (int i = 1; i < list.Count; i++)
|
||||
{
|
||||
String metadatum = list[i];
|
||||
int equals = metadatum.IndexOf('=');
|
||||
if (equals < 0)
|
||||
{
|
||||
// take the whole thing as a usable label
|
||||
type = metadatum;
|
||||
break;
|
||||
}
|
||||
if (String.Compare("TYPE", metadatum.Substring(0, equals), StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
type = metadatum.Substring(equals + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.Add(type);
|
||||
}
|
||||
}
|
||||
return SupportClass.toStringArray(result);
|
||||
}
|
||||
|
||||
private static bool isLikeVCardDate(String value)
|
||||
{
|
||||
return value == null || VCARD_LIKE_DATE.Match(value).Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats name fields of the form "Public;John;Q.;Reverend;III" into a form like
|
||||
* "Reverend John Q. Public III".
|
||||
*
|
||||
* @param names name values to format, in place
|
||||
*/
|
||||
private static void formatNames(IEnumerable<List<String>> names)
|
||||
{
|
||||
if (names != null)
|
||||
{
|
||||
foreach (var list in names)
|
||||
{
|
||||
String name = list[0];
|
||||
String[] components = new String[5];
|
||||
int start = 0;
|
||||
int end;
|
||||
int componentIndex = 0;
|
||||
while (componentIndex < components.Length - 1 && (end = name.IndexOf(';', start)) >= 0)
|
||||
{
|
||||
components[componentIndex] = name.Substring(start, end - start);
|
||||
|
||||
|
||||
componentIndex++;
|
||||
start = end + 1;
|
||||
}
|
||||
components[componentIndex] = name.Substring(start);
|
||||
StringBuilder newName = new StringBuilder(100);
|
||||
maybeAppendComponent(components, 3, newName);
|
||||
maybeAppendComponent(components, 1, newName);
|
||||
maybeAppendComponent(components, 2, newName);
|
||||
maybeAppendComponent(components, 0, newName);
|
||||
maybeAppendComponent(components, 4, newName);
|
||||
list.Insert(0, newName.ToString().Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void maybeAppendComponent(String[] components, int i, StringBuilder newName)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(components[i]))
|
||||
{
|
||||
if (newName.Length > 0)
|
||||
{
|
||||
newName.Append(' ');
|
||||
}
|
||||
newName.Append(components[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
146
Others/zxing.core/zxing.core/client/result/VEventResultParser.cs
Normal file
146
Others/zxing.core/zxing.core/client/result/VEventResultParser.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.Globalization;
|
||||
|
||||
namespace ZXing.Client.Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Partially implements the iCalendar format's "VEVENT" format for specifying a
|
||||
/// calendar event. See RFC 2445. This supports SUMMARY, DTSTART and DTEND fields.
|
||||
/// </summary>
|
||||
/// <author> Sean Owen
|
||||
/// </author>
|
||||
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
|
||||
/// </author>
|
||||
sealed class VEventResultParser : ResultParser
|
||||
{
|
||||
override public ParsedResult parse(ZXing.Result result)
|
||||
{
|
||||
String rawText = result.Text;
|
||||
if (rawText == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int vEventStart = rawText.IndexOf("BEGIN:VEVENT");
|
||||
if (vEventStart < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String summary = matchSingleVCardPrefixedField("SUMMARY", rawText);
|
||||
String start = matchSingleVCardPrefixedField("DTSTART", rawText);
|
||||
if (start == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String end = matchSingleVCardPrefixedField("DTEND", rawText);
|
||||
String duration = matchSingleVCardPrefixedField("DURATION", rawText);
|
||||
String location = matchSingleVCardPrefixedField("LOCATION", rawText);
|
||||
String organizer = stripMailto(matchSingleVCardPrefixedField("ORGANIZER", rawText));
|
||||
|
||||
String[] attendees = matchVCardPrefixedField("ATTENDEE", rawText);
|
||||
if (attendees != null)
|
||||
{
|
||||
for (int i = 0; i < attendees.Length; i++)
|
||||
{
|
||||
attendees[i] = stripMailto(attendees[i]);
|
||||
}
|
||||
}
|
||||
String description = matchSingleVCardPrefixedField("DESCRIPTION", rawText);
|
||||
|
||||
String geoString = matchSingleVCardPrefixedField("GEO", rawText);
|
||||
double latitude;
|
||||
double longitude;
|
||||
if (geoString == null)
|
||||
{
|
||||
latitude = Double.NaN;
|
||||
longitude = Double.NaN;
|
||||
}
|
||||
else
|
||||
{
|
||||
int semicolon = geoString.IndexOf(';');
|
||||
if (semicolon < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
#if WindowsCE
|
||||
try { latitude = Double.Parse(geoString.Substring(0, semicolon), NumberStyles.Float, CultureInfo.InvariantCulture); }
|
||||
catch { return null; }
|
||||
try { longitude = Double.Parse(geoString.Substring(semicolon + 1), NumberStyles.Float, CultureInfo.InvariantCulture); }
|
||||
catch { return null; }
|
||||
#else
|
||||
if (!Double.TryParse(geoString.Substring(0, semicolon), NumberStyles.Float, CultureInfo.InvariantCulture, out latitude))
|
||||
return null;
|
||||
if (!Double.TryParse(geoString.Substring(semicolon + 1), NumberStyles.Float, CultureInfo.InvariantCulture, out longitude))
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new CalendarParsedResult(summary,
|
||||
start,
|
||||
end,
|
||||
duration,
|
||||
location,
|
||||
organizer,
|
||||
attendees,
|
||||
description,
|
||||
latitude,
|
||||
longitude);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String matchSingleVCardPrefixedField(String prefix,
|
||||
String rawText)
|
||||
{
|
||||
var values = VCardResultParser.matchSingleVCardPrefixedField(prefix, rawText, true, false);
|
||||
return values == null || values.Count == 0 ? null : values[0];
|
||||
}
|
||||
|
||||
private static String[] matchVCardPrefixedField(String prefix, String rawText)
|
||||
{
|
||||
List<List<String>> values = VCardResultParser.matchVCardPrefixedField(prefix, rawText, true, false);
|
||||
if (values == null || values.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int size = values.Count;
|
||||
String[] result = new String[size];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
result[i] = values[i][0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String stripMailto(String s)
|
||||
{
|
||||
if (s != null && (s.StartsWith("mailto:") || s.StartsWith("MAILTO:")))
|
||||
{
|
||||
s = s.Substring(7);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user