Browse Source

add reader

tags/3.2
clowwindy 10 years ago
parent
commit
7927811ba3
13 changed files with 1723 additions and 0 deletions
  1. +89
    -0
      shadowsocks-csharp/3rd/zxing/BarcodeFormat.cs
  2. +206
    -0
      shadowsocks-csharp/3rd/zxing/BaseLuminanceSource.cs
  3. +104
    -0
      shadowsocks-csharp/3rd/zxing/Binarizer.cs
  4. +186
    -0
      shadowsocks-csharp/3rd/zxing/BinaryBitmap.cs
  5. +242
    -0
      shadowsocks-csharp/3rd/zxing/BitmapLuminanceSource.cs
  6. +198
    -0
      shadowsocks-csharp/3rd/zxing/LuminanceSource.cs
  7. +59
    -0
      shadowsocks-csharp/3rd/zxing/Reader.cs
  8. +71
    -0
      shadowsocks-csharp/3rd/zxing/ReaderException.cs
  9. +161
    -0
      shadowsocks-csharp/3rd/zxing/Result.cs
  10. +102
    -0
      shadowsocks-csharp/3rd/zxing/ResultMetadataType.cs
  11. +255
    -0
      shadowsocks-csharp/3rd/zxing/qrcode/QRCodeReader.cs
  12. +39
    -0
      shadowsocks-csharp/View/MenuViewController.cs
  13. +11
    -0
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 89
- 0
shadowsocks-csharp/3rd/zxing/BarcodeFormat.cs View File

@@ -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.
*/
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>
/// 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)
/// </summary>
All_1D = UPC_A | UPC_E | EAN_13 | EAN_8 | CODABAR | CODE_39 | CODE_93 | CODE_128 | ITF | RSS_14 | RSS_EXPANDED
}
}

+ 206
- 0
shadowsocks-csharp/3rd/zxing/BaseLuminanceSource.cs View File

@@ -0,0 +1,206 @@
/*
* 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
protected const int RChannelWeight = 19562;
protected const int GChannelWeight = 38550;
protected const int BChannelWeight = 7424;
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 &lt;= y &lt; 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;
}
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 &lt;= left &lt; Width.</param>
/// <param name="top">The top coordinate, 0 &lt;= top &lt;= 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>
/// 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
- 0
shadowsocks-csharp/3rd/zxing/Binarizer.cs View 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, 0 &lt;= y &lt; 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; }
}
}
}

+ 186
- 0
shadowsocks-csharp/3rd/zxing/BinaryBitmap.cs View File

@@ -0,0 +1,186 @@
/*
* 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>
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
/// </author>
public sealed class BinaryBitmap
{
private Binarizer binarizer;
private BitMatrix matrix;
public BinaryBitmap(Binarizer binarizer)
{
if (binarizer == null)
{
throw new ArgumentException("Binarizer must be non-null.");
}
this.binarizer = binarizer;
}
/// <returns> The width of the bitmap.
/// </returns>
public int Width
{
get
{
return binarizer.Width;
}
}
/// <returns> The height of the bitmap.
/// </returns>
public int Height
{
get
{
return binarizer.Height;
}
}
/// <summary> Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
/// cached data. Callers should assume this method is expensive and call it as seldom as possible.
/// This method is intended for decoding 1D barcodes and may choose to apply sharpening.
///
/// </summary>
/// <param name="y">The row to fetch, 0 &lt;= y &lt; 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.
if (matrix == null)
{
matrix = binarizer.BlackMatrix;
}
return matrix;
}
}
/// <returns> Whether this bitmap can be cropped.
/// </returns>
public bool CropSupported
{
get
{
return binarizer.LuminanceSource.CropSupported;
}
}
/// <summary> Returns a new object with cropped image data. Implementations may keep a reference to the
/// original data rather than a copy. Only callable if isCropSupported() is true.
///
/// </summary>
/// <param name="left">The left coordinate, 0 &lt;= left &lt; getWidth().
/// </param>
/// <param name="top">The top coordinate, 0 &lt;= top &lt;= getHeight().
/// </param>
/// <param name="width">The width of the rectangle to crop.
/// </param>
/// <param name="height">The height of the rectangle to crop.
/// </param>
/// <returns> A cropped version of this object.
/// </returns>
public BinaryBitmap crop(int left, int top, int width, int height)
{
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 {@link #isRotateSupported()} 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 {@link #isRotateSupported()} is true.
/// </summary>
/// <returns>A rotated version of this object.</returns>
public BinaryBitmap rotateCounterClockwise45()
{
LuminanceSource newSource = binarizer.LuminanceSource.rotateCounterClockwise45();
return new BinaryBitmap(binarizer.createBinarizer(newSource));
}
/// <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;
}
}
}

+ 242
- 0
shadowsocks-csharp/3rd/zxing/BitmapLuminanceSource.cs View File

@@ -0,0 +1,242 @@
/*
* 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
{
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)
{
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
Color c;
for (int y = 0; y < height; y++)
{
int offset = y*width;
for (int x = 0; x < width; x++)
{
c = bitmap.GetPixel(x, y);
luminances[offset + x] = (byte)((RChannelWeight * c.R + GChannelWeight * c.G + BChannelWeight * c.B) >> ChannelWeight);
}
}
}
else
{
var strideStep = data.Stride;
var buffer = new byte[stride];
var ptrInBitmap = data.Scan0;
#if !WindowsCE
// prepare palette for 1 and 8 bit indexed bitmaps
var luminancePalette = new byte[bitmap.Palette.Entries.Length];
for (var index = 0; index < bitmap.Palette.Entries.Length; index++)
{
var color = bitmap.Palette.Entries[index];
luminancePalette[index] = (byte) ((RChannelWeight*color.R +
GChannelWeight*color.G +
BChannelWeight*color.B) >> ChannelWeight);
}
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
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
ptrInBitmap = IntPtr.Add(ptrInBitmap, strideStep);
#else
ptrInBitmap = new IntPtr(ptrInBitmap.ToInt64() + strideStep);
#endif
var offset = y*width;
switch (pixelWidth)
{
#if !WindowsCE
case 0:
for (int x = 0; x*8 < width; x++)
{
for (int subX = 0; subX < 8 && 8*x + subX < width; subX++)
{
var index = (buffer[x] >> (7 - subX)) & 1;
luminances[offset + 8*x + subX] = luminancePalette[index];
}
}
break;
case 1:
for (int x = 0; x < width; x++)
{
luminances[offset + x] = luminancePalette[buffer[x]];
}
break;
#endif
case 2:
// should be RGB565 or RGB555, assume RGB565
{
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++;
}
}
break;
case 3:
{
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++;
}
}
break;
case 4:
// 4 bytes without alpha channel value
{
var maxIndex = 4*width;
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++;
}
}
break;
case 40:
// 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
{
var maxIndex = 4*width;
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++;
}
}
break;
case 41:
// CMYK color space
{
var maxIndex = 4 * 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++;
}
}
break;
default:
throw new NotSupportedException();
}
}
}
}
finally
{
bitmap.UnlockBits(data);
}
}
/// <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 };
}
}
}

+ 198
- 0
shadowsocks-csharp/3rd/zxing/LuminanceSource.cs View File

@@ -0,0 +1,198 @@
/*
* 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>
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
/// </author>
public abstract class LuminanceSource
{
private int width;
private int height;
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, 0 &lt;= y &lt; 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:
/// int luminance = array[y * width + x] &amp; 0xff;
///
/// </summary>
/// <returns> A row-major 2D array of luminance values. Do not use result.length as it may be
/// larger than width * height bytes on some platforms. Do not modify the contents
/// of the result.
/// </returns>
public abstract byte[] Matrix { get; }
/// <returns> The width of the bitmap.</returns>
virtual public int Width
{
get
{
return width;
}
protected set
{
width = value;
}
}
/// <returns> The height of the bitmap.</returns>
virtual public int Height
{
get
{
return height;
}
protected set
{
height = value;
}
}
/// <returns> Whether this subclass supports cropping.</returns>
virtual public 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, 0 &lt;= left &lt; Width.
/// </param>
/// <param name="top">The top coordinate, 0 &lt;= top &lt;= 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>
virtual public bool RotateSupported
{
get
{
return false;
}
}
/// <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 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 {@link #isRotateSupported()} 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>
virtual public bool InversionSupported
{
get
{
return false;
}
}
override public String ToString()
{
var row = new byte[width];
var result = new StringBuilder(height * (width + 1));
for (int y = 0; y < height; y++)
{
row = getRow(y, row);
for (int x = 0; x < width; x++)
{
int luminance = row[x] & 0xFF;
char c;
if (luminance < 0x40)
{
c = '#';
}
else if (luminance < 0x80)
{
c = '+';
}
else if (luminance < 0xC0)
{
c = '.';
}
else
{
c = ' ';
}
result.Append(c);
}
result.Append('\n');
}
return result.ToString();
}
}
}

+ 59
- 0
shadowsocks-csharp/3rd/zxing/Reader.cs View 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();
}
}

+ 71
- 0
shadowsocks-csharp/3rd/zxing/ReaderException.cs View File

@@ -0,0 +1,71 @@
/*
* 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>
/// Gets the instance.
/// </summary>
public static ReaderException Instance
{
get
{
return instance;
}
}
// TODO: Currently we throw up to 400 ReaderExceptions while scanning a single 240x240 image before
// rejecting it. This involves a lot of overhead and memory allocation, and affects both performance
// and latency on continuous scan clients. In the future, we should change all the decoders not to
// throw exceptions for routine events, like not finding a barcode on a given row. Instead, we
// should return error codes back to the callers, and simply delete this class. In the mean time, I
// have altered this class to be as lightweight as possible, by ignoring the exception string, and
// by disabling the generation of stack traces, which is especially time consuming. These are just
// temporary measures, pending the big cleanup.
//UPGRADE_NOTE: Final was removed from the declaration of 'instance '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
private static readonly ReaderException instance = new ReaderException();
// EXCEPTION TRACKING SUPPORT
// Identifies who is throwing exceptions and how often. To use:
//
// 1. Uncomment these lines and the code below which uses them.
// 2. Uncomment the two corresponding lines in j2se/CommandLineRunner.decode()
// 3. Change core to build as Java 1.5 temporarily
// private static int exceptionCount = 0;
// private static Map<String,Integer> throwers = new HashMap<String,Integer>(32);
/// <summary>
/// Initializes a new instance of the <see cref="ReaderException"/> class.
/// </summary>
protected ReaderException()
{
// do nothing
}
}
}

+ 161
- 0
shadowsocks-csharp/3rd/zxing/Result.cs View File

@@ -0,0 +1,161 @@
/*
* 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>
/// 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, 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)
{
if (text == null && rawBytes == null)
{
throw new ArgumentException("Text and bytes are null");
}
Text = text;
RawBytes = rawBytes;
ResultPoints = resultPoints;
BarcodeFormat = format;
ResultMetadata = null;
Timestamp = timestamp;
}
/// <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
- 0
shadowsocks-csharp/3rd/zxing/ResultMetadataType.cs View 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
}
}

+ 255
- 0
shadowsocks-csharp/3rd/zxing/qrcode/QRCodeReader.cs View File

@@ -0,0 +1,255 @@
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using ZXing.Common;
using ZXing.QrCode.Internal;
namespace ZXing.QrCode
{
/// <summary>
/// This implementation can detect and decode QR Codes in an image.
/// <author>Sean Owen</author>
/// </summary>
public class QRCodeReader : Reader
{
private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0];
private readonly Decoder decoder = new Decoder();
/// <summary>
/// Gets the decoder.
/// </summary>
/// <returns></returns>
protected Decoder getDecoder()
{
return decoder;
}
/// <summary>
/// Locates and decodes a QR code in an image.
///
/// <returns>a String representing the content encoded by the QR code</returns>
/// </summary>
public Result decode(BinaryBitmap image)
{
return decode(image, null);
}
/// <summary>
/// Locates and decodes a barcode in some format within an image. This method also accepts
/// hints, each possibly associated to some data, which may help the implementation decode.
/// </summary>
/// <param name="image">image of barcode to decode</param>
/// <param name="hints">passed as a <see cref="IDictionary{TKey, TValue}"/> from <see cref="DecodeHintType"/>
/// to arbitrary data. The
/// meaning of the data depends upon the hint type. The implementation may or may not do
/// anything with these hints.</param>
/// <returns>
/// String which the barcode encodes
/// </returns>
public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
DecoderResult decoderResult;
ResultPoint[] points;
if (image == null || image.BlackMatrix == null)
{
// something is wrong with the image
return null;
}
if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE))
{
var bits = extractPureBits(image.BlackMatrix);
if (bits == null)
return null;
decoderResult = decoder.decode(bits, hints);
points = NO_POINTS;
}
else
{
var detectorResult = new Detector(image.BlackMatrix).detect(hints);
if (detectorResult == null)
return null;
decoderResult = decoder.decode(detectorResult.Bits, hints);
points = detectorResult.Points;
}
if (decoderResult == null)
return null;
// If the code was mirrored: swap the bottom-left and the top-right points.
var data = decoderResult.Other as QRCodeDecoderMetaData;
if (data != null)
{
data.applyMirroredCorrection(points);
}
var result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE);
var byteSegments = decoderResult.ByteSegments;
if (byteSegments != null)
{
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments);
}
var ecLevel = decoderResult.ECLevel;
if (ecLevel != null)
{
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
}
if (decoderResult.StructuredAppend)
{
result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE, decoderResult.StructuredAppendSequenceNumber);
result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY, decoderResult.StructuredAppendParity);
}
return result;
}
/// <summary>
/// Resets any internal state the implementation has after a decode, to prepare it
/// for reuse.
/// </summary>
public void reset()
{
// do nothing
}
/// <summary>
/// This method detects a code in a "pure" image -- that is, pure monochrome image
/// which contains only an unrotated, unskewed, image of a code, with some white border
/// around it. This is a specialized method that works exceptionally fast in this special
/// case.
///
/// <seealso cref="ZXing.Datamatrix.DataMatrixReader.extractPureBits(BitMatrix)" />
/// </summary>
private static BitMatrix extractPureBits(BitMatrix image)
{
int[] leftTopBlack = image.getTopLeftOnBit();
int[] rightBottomBlack = image.getBottomRightOnBit();
if (leftTopBlack == null || rightBottomBlack == null)
{
return null;
}
float moduleSize;
if (!QRCodeReader.moduleSize(leftTopBlack, image, out moduleSize))
return null;
int top = leftTopBlack[1];
int bottom = rightBottomBlack[1];
int left = leftTopBlack[0];
int right = rightBottomBlack[0];
// Sanity check!
if (left >= right || top >= bottom)
{
return null;
}
if (bottom - top != right - left)
{
// Special case, where bottom-right module wasn't black so we found something else in the last row
// Assume it's a square, so use height as the width
right = left + (bottom - top);
}
int matrixWidth = (int)Math.Round((right - left + 1) / moduleSize);
int matrixHeight = (int)Math.Round((bottom - top + 1) / moduleSize);
if (matrixWidth <= 0 || matrixHeight <= 0)
{
return null;
}
if (matrixHeight != matrixWidth)
{
// Only possibly decode square regions
return null;
}
// Push in the "border" by half the module width so that we start
// sampling in the middle of the module. Just in case the image is a
// little off, this will help recover.
int nudge = (int)(moduleSize / 2.0f);
top += nudge;
left += nudge;
// But careful that this does not sample off the edge
int nudgedTooFarRight = left + (int)((matrixWidth - 1) * moduleSize) - (right - 1);
if (nudgedTooFarRight > 0)
{
if (nudgedTooFarRight > nudge)
{
// Neither way fits; abort
return null;
}
left -= nudgedTooFarRight;
}
int nudgedTooFarDown = top + (int)((matrixHeight - 1) * moduleSize) - (bottom - 1);
if (nudgedTooFarDown > 0)
{
if (nudgedTooFarDown > nudge)
{
// Neither way fits; abort
return null;
}
top -= nudgedTooFarDown;
}
// Now just read off the bits
BitMatrix bits = new BitMatrix(matrixWidth, matrixHeight);
for (int y = 0; y < matrixHeight; y++)
{
int iOffset = top + (int)(y * moduleSize);
for (int x = 0; x < matrixWidth; x++)
{
if (image[left + (int)(x * moduleSize), iOffset])
{
bits[x, y] = true;
}
}
}
return bits;
}
private static bool moduleSize(int[] leftTopBlack, BitMatrix image, out float msize)
{
int height = image.Height;
int width = image.Width;
int x = leftTopBlack[0];
int y = leftTopBlack[1];
bool inBlack = true;
int transitions = 0;
while (x < width && y < height)
{
if (inBlack != image[x, y])
{
if (++transitions == 5)
{
break;
}
inBlack = !inBlack;
}
x++;
y++;
}
if (x == width || y == height)
{
msize = 0.0f;
return false;
}
msize = (x - leftTopBlack[0]) / 7.0f;
return true;
}
}
}

+ 39
- 0
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -357,6 +357,45 @@ namespace Shadowsocks.View
qrCodeForm.Show();
}
private void ScanQRCodeItem_Click(object sender, EventArgs e)
{
/*
using (Bitmap image = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height))
{
using (Graphics g = Graphics.FromImage(bmpScreenCapture))
{
g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0, 0,
bmpScreenCapture.Size,
CopyPixelOperation.SourceCopy);
}
resultPoints.Clear();
/* var reader = new BarcodeReader
{
PossibleFormats = new List<BarcodeFormat>
{
BarcodeFormat.QR_CODE
}
};
var result = reader.Decode(image);
var result = barcodeReader.Decode(image);
var timerStart = DateTime.Now.Ticks;
var timerStop = DateTime.Now.Ticks;
if (result == null)
{
txtDecoderContent.Text = "No barcode recognized";
}
labDuration.Text = new TimeSpan(timerStop - timerStart).Milliseconds.ToString("0 ms");
}
}
* */
}
private void AutoStartupItem_Click(object sender, EventArgs e) {
AutoStartupItem.Checked = !AutoStartupItem.Checked;
if (!AutoStartup.Set(AutoStartupItem.Checked)) {


+ 11
- 0
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -70,6 +70,11 @@
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<Compile Include="3rd\zxing\BarcodeFormat.cs" />
<Compile Include="3rd\zxing\BaseLuminanceSource.cs" />
<Compile Include="3rd\zxing\Binarizer.cs" />
<Compile Include="3rd\zxing\BinaryBitmap.cs" />
<Compile Include="3rd\zxing\BitmapLuminanceSource.cs" />
<Compile Include="3rd\zxing\common\BitArray.cs" />
<Compile Include="3rd\zxing\common\BitMatrix.cs" />
<Compile Include="3rd\zxing\common\BitSource.cs" />
@@ -88,6 +93,7 @@
<Compile Include="3rd\zxing\common\reedsolomon\ReedSolomonEncoder.cs" />
<Compile Include="3rd\zxing\DecodeHintType.cs" />
<Compile Include="3rd\zxing\EncodeHintType.cs" />
<Compile Include="3rd\zxing\LuminanceSource.cs" />
<Compile Include="3rd\zxing\qrcode\decoder\BitMatrixParser.cs" />
<Compile Include="3rd\zxing\qrcode\decoder\DataBlock.cs" />
<Compile Include="3rd\zxing\qrcode\decoder\DataMask.cs" />
@@ -112,6 +118,11 @@
<Compile Include="3rd\zxing\qrcode\encoder\QRCode.cs" />
<Compile Include="3rd\zxing\qrcode\encoder\QrCodeEncodingOptions.cs" />
<Compile Include="3rd\SimpleJson.cs" />
<Compile Include="3rd\zxing\qrcode\QRCodeReader.cs" />
<Compile Include="3rd\zxing\Reader.cs" />
<Compile Include="3rd\zxing\ReaderException.cs" />
<Compile Include="3rd\zxing\Result.cs" />
<Compile Include="3rd\zxing\ResultMetadataType.cs" />
<Compile Include="3rd\zxing\ResultPoint.cs" />
<Compile Include="3rd\zxing\ResultPointCallback.cs" />
<Compile Include="3rd\zxing\WriterException.cs" />


Loading…
Cancel
Save