免費開源的DotNet二維碼操作組件ThoughtWorks.QRCode(.NET組件介紹之四)

    在生活中有一種東西幾乎已經快要成爲我們的另一個電子」身份證「,那就是二維碼。無論是在軟件開發的過程中,還是在普通用戶的日常中,幾乎都離不開二維碼。二維碼 (dimensional barcode) ,又稱二維條碼,是在一維條碼的基礎上擴展出的一種具有可讀性的條碼。設備掃描二維條碼,通過識別條碼的長度和寬度中所記載的二進制數據,可獲取其中所包含的信息。相比一維條碼,二維碼記載更復雜的數據,比如圖片、網絡鏈接等。

   今天介紹一種免費開源的二維碼操作組件,ThoughtWorks.QRCode組件可以高效而穩定的生成我們需要的二維碼,接下來我們詳細的瞭解一下這個組件。

一.ThoughtWorks.QRCode組件概述:

     QRCode庫是一個.NET組件,可用於編碼和解碼QRCode。 QRCode是源自日本的二維條形碼。 現在,它廣泛應用於廣泛的工業領域。 用於車輛部件跟蹤和庫存管理。QR代表「快速反應」。 它是日本公司Denso-Wave在1994年創建的,目的是高速解碼內容。 如今,QR碼被用於手機中以緩解數據輸入。QRCode還可以打印在名片上或顯示在任何顯示器上,然後可以由移動電話捕獲,只要移動電話具有讀取QRCode的軟件。QRCode庫提供的功能包括:將內容編碼爲QR碼圖像,可以保存爲JPEG,GIF,PNG或位圖格式;解碼QR碼圖像。

    該庫可用於任何.NET 2.0 Windows應用程序,ASP.NET Web應用程序或Windows Mobile設備應用程序。以下是該組件的聲明」本文以及任何相關的源代碼和文件均已獲得代碼項目開放許可證(CPOL)許可「。

二.ThoughtWorks.QRCode相關核心對象和方法解析:

    有關ThoughtWorks.QRCode的主要類如下:

     以上是採用.NET Reflector對DLL文件進行反編譯,以此查看源代碼。由於我只是下載了DLL文件,沒有下載源碼,所以直接利用.NET Reflector查看源碼,接下來具體介紹一下組件的一些類和方法:

   1.QRCodeEncoder:二維碼編碼類。

public enum ENCODE_MODE
{
    ALPHA_NUMERIC,
    NUMERIC,
    BYTE
}

public enum ERROR_CORRECTION
{
    L,
    M,
    Q,
    H
}

public virtual Bitmap Encode(string content, Encoding encoding)
{
    bool[][] flagArray = this.calQrcode(encoding.GetBytes(content));
    SolidBrush brush = new SolidBrush(this.qrCodeBackgroundColor);
    Bitmap image = new Bitmap((flagArray.Length * this.qrCodeScale) + 1, (flagArray.Length * this.qrCodeScale) + 1);
    Graphics graphics = Graphics.FromImage(image);
    graphics.FillRectangle(brush, new Rectangle(0, 0, image.Width, image.Height));
    brush.Color = this.qrCodeForegroundColor;
    for (int i = 0; i < flagArray.Length; i++)
    {
        for (int j = 0; j < flagArray.Length; j++)
        {
            if (flagArray[j][i])
            {
                graphics.FillRectangle(brush, j * this.qrCodeScale, i * this.qrCodeScale, this.qrCodeScale, this.qrCodeScale);
            }
        }
    }
    return image;
}

   2.QRCodeDecoder:二維碼解碼類。

public virtual string decode(QRCodeImage qrCodeImage, Encoding encoding)
{
    sbyte[] src = this.decodeBytes(qrCodeImage);
    byte[] dst = new byte[src.Length];
    Buffer.BlockCopy(src, 0, dst, 0, dst.Length);
    return encoding.GetString(dst);
}

 
public virtual sbyte[] decodeBytes(QRCodeImage qrCodeImage)
{
    DecodeResult result;
    Point[] adjustPoints = this.AdjustPoints;
    ArrayList list = ArrayList.Synchronized(new ArrayList(10));
    while (this.numTryDecode < adjustPoints.Length)
    {
        try
        {
            result = this.decode(qrCodeImage, adjustPoints[this.numTryDecode]);
            if (result.CorrectionSucceeded)
            {
                return result.DecodedBytes;
            }
            list.Add(result);
            canvas.println("Decoding succeeded but could not correct");
            canvas.println("all errors. Retrying..");
        }
        catch (DecodingFailedException exception)
        {
            if (exception.Message.IndexOf("Finder Pattern") >= 0)
            {
                throw exception;
            }
        }
        finally
        {
            this.numTryDecode++;
        }
    }
    if (list.Count == 0)
    {
        throw new DecodingFailedException("Give up decoding");
    }
    int num = -1;
    int numErrors = 0x7fffffff;
    for (int i = 0; i < list.Count; i++)
    {
        result = (DecodeResult) list[i];
        if (result.NumErrors < numErrors)
        {
            numErrors = result.NumErrors;
            num = i;
        }
    }
    canvas.println("All trials need for correct error");
    canvas.println("Reporting #" + num + " that,");
    canvas.println("corrected minimum errors (" + numErrors + ")");
    canvas.println("Decoding finished.");
    return ((DecodeResult) list[num]).DecodedBytes;
}

   3.QRCodeBitmapImage:位圖圖像。

public class QRCodeBitmapImage : QRCodeImage
{
    // Fields
    private Bitmap image;

    // Methods
    public QRCodeBitmapImage(Bitmap image);
    public virtual int getPixel(int x, int y);

    // Properties
    public virtual int Height { get; }
    public virtual int Width { get; }
}
public interface QRCodeImage
{
    // Methods
    int getPixel(int x, int y);

    // Properties
    int Height { get; }
    int Width { get; }
}

   以上是對ThoughtWorks.QRCode組件的一些方法的介紹,如果需要了解更多的方法,可以查看對應的源碼。

三.ThoughtWorks.QRCode二維碼操作實例:

    1.生成二維碼(對二維碼沒有進行設置)。

        /// <summary>
        /// 生成二維碼
        /// </summary>
        /// <param name="content">帶生成二維碼的字符串</param>
        /// <param name="path">路徑</param>
        /// <returns></returns>
        public static string CreatehoughtWorksQrCode(string content, string path)
        {
            if (string.IsNullOrEmpty(content))
            {
                throw new ArgumentNullException(content);
            }
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(path);
            }
            var qrCodeEncoder = new QRCodeEncoder
            {
                QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
                QRCodeScale = 4,
                QRCodeVersion = 8,
                QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M
            };
            Image image = qrCodeEncoder.Encode(content);
            var filename = DateTime.Now.ToString("yyyymmddhhmmssfff") + ".jpg";
            var filepath = string.Format("{0}{1}", path, filename);
            FileStream fs = null;
            try
            {
                fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);
                image.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (IOException ex)
            {
                throw new IOException(ex.Message);
            }
            finally
            {
                if (fs != null) fs.Close();
                image.Dispose();
            }
            return CodeDecoder(filepath);
        }

    2.選擇生成二維碼的相關類型。

        /// <summary>
        /// 選擇生成二維碼的相關類型
        /// <param name="strData">要生成的文字或者數字,支持中文。如: "4408810820 深圳-廣州" 或者:4444444444</param>
        /// <param name="qrEncoding">三種尺寸:BYTE ,ALPHA_NUMERIC,NUMERIC</param>
        /// <param name="level">大小:L M Q H</param>
        /// <param name="version">版本:如 8</param>
        /// <param name="scale">比例:如 4</param>
        /// <returns></returns>
        /// </summary>
        public void CreateCode_Choose(string strData, string qrEncoding, string level, int version, int scale)
        {
            if (string.IsNullOrEmpty(strData))
            {
                throw new ArgumentNullException(strData);
            }
            if (string.IsNullOrEmpty(qrEncoding))
            {
                throw new ArgumentNullException(qrEncoding);
            }
            if (string.IsNullOrEmpty(level))
            {
                throw new ArgumentNullException(level);
            }
            var qrCodeEncoder = new QRCodeEncoder();
            var encoding = qrEncoding;
            switch (encoding)
            {
                case "Byte":
                    qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
                    break;
                case "AlphaNumeric":
                    qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.ALPHA_NUMERIC;
                    break;
                case "Numeric":
                    qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.NUMERIC;
                    break;
                default:
                    qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
                    break;
            }
            qrCodeEncoder.QRCodeScale = scale;
            qrCodeEncoder.QRCodeVersion = version;
            switch (level)
            {
                case "L":
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L;
                    break;
                case "M":
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
                    break;
                case "Q":
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.Q;
                    break;
                default:
                    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
                    break;
            }
            Image image = null;
            FileStream fs = null;
            try
            {
                //文字生成圖片
                image = qrCodeEncoder.Encode(strData);
                var filename = DateTime.Now.ToString("yyyymmddhhmmssfff") + ".jpg";
                var filepath = HttpContext.Current.Server.MapPath(@"~\Upload") + "\\" + filename;
                fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);
                image.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (IOException ioex)
            {
                throw new IOException(ioex.Message);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                if (fs != null) fs.Close();
                if (image != null) image.Dispose();
            }
        }

   3.二維碼解碼。

        /// <summary>
        /// 二維碼解碼
        /// </summary>
        /// <param name="filePath">圖片路徑</param>
        /// <returns></returns>
        public static string CodeDecoder(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException(filePath);
            }
            try
            {
                if (!File.Exists(filePath))
                    return null;
                var myBitmap = new Bitmap(Image.FromFile(filePath));
                var decoder = new QRCodeDecoder();
                var decodedString = decoder.decode(new QRCodeBitmapImage(myBitmap));
                return decodedString;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

四.總結:

    跟以前介紹組件一樣,首先是組件的概述,組件的核心類,組件的使用方法,這些在這個組件時,找改組件的相關概述時,花了不少時間,也不知道爲何,這個組件沒有找到相關的資料,甚至連作者都是以某某某代替,最後還是在這裏找到一些介紹:https://www.codeproject.com/articles/20574/open-source-qrcode-library。但是互聯網就是如此,我們不需要知道是誰製造的,只要用起來方便就可以。在生成二維碼的組件和js插件中,我個人還是喜歡這個組件的,感覺很不錯,任何組件和方法都是有個人偏好和使用環境,讀者可以自行根據情況選擇。

   由於開發者提供了一個demo,可以直接進入上面的鏈接中查看下載,在這裏就不做一個示例介紹。

 

.NET組件介紹系列:

    一款開源免費的.NET文檔操作組件DocX(.NET組件介紹之一)http://www.cnblogs.com/pengze0902/p/6122311.html

    高效而穩定的企業級.NET Office 組件Spire(.NET組件介紹之二)http://www.cnblogs.com/pengze0902/p/6125570.html

    最好的.NET開源免費ZIP庫DotNetZip(.NET組件介紹之三)http://www.cnblogs.com/pengze0902/p/6124659.html

    免費開源的DotNet二維碼操作組件ThoughtWorks.QRCode(.NET組件介紹之四)http://www.cnblogs.com/pengze0902/p/6134506.html

    免費開源的DotNet任務調度組件Quartz.NET(.NET組件介紹之五)http://www.cnblogs.com/pengze0902/p/6128558.html

    免費高效實用的Excel操作組件NPOI(.NET組件介紹之六)http://www.cnblogs.com/pengze0902/p/6150070.html