/// <summary> /// Trả về link ảnh từ dịch vụ QRCode của Google /// </summary> /// <param name="Text">Văn bản cần sinh mã QR</param> /// <param name="ImageSize">Kích thước của ảnh QR. Tối đa là 500 px</param> /// <param name="Correction">Mức độ chịu lỗi</param> /// <param name="Margin">Số điểm ảnh trắng để làm biên </param> /// <returns></returns> static string GetQRCodeWebAPI(string Text, int ImageSize = 500, CorrectionLevel Correction = CorrectionLevel.High, int Margin = 0) { StringBuilder sURL = new StringBuilder(); sURL.AppendFormat("https://chart.googleapis.com/chart?cht=qr&chs={0}x{0}&chld={1}|{2}&chl={3}", ImageSize, Correction, Margin, Text); return(sURL.ToString()); }
public static DataBlock BlockMaker(string data, CorrectionLevel level, int version) { var d = new StringBuilder(data); var res = BlockStrToBlockInt(d); return(new DataBlock(res.ToList(), level, version)); }
private static byte[] CodingByte(byte[] Bytes, int Version, CorrectionLevel Level) { #region Кодирование (Data) BitSequence Data = new BitSequence(Bytes); #endregion #region Добавление служебных полей (DataTmp) int MaxLength = MaxCapacity[(int)Level, Version - 1]; BitSequence TypeCode = new BitSequence(new bool[] { false, true, false, false }); byte[] BytesCount = (Version < 10 ? new byte[] { (byte)(Bytes.Length & 0x00FF) } : new byte[] { (byte)((Bytes.Length & 0xFF00) >> 8), (byte)(Bytes.Length & 0x00FF) }); BitSequence DataLength = new BitSequence(BytesCount); BitSequence ResultBits = TypeCode + DataLength + Data; if (ResultBits.Length > MaxLength) { throw new Exception(ErrorLongData); } byte[] DataTmp = ResultBits.ToByteArray(); #endregion #region Дополнение (Result) byte[] Result = new byte[MaxLength / 8]; DataTmp.CopyTo(Result, 0); bool f = true; for (int i = DataTmp.Length; i < Result.Length; i++) { Result[i] = (f ? (byte)0b11101100 : (byte)0b00010001); f = !f; } #endregion return(Result); }
private static int GetVersion(CorrectionLevel level, int dataLenght) { for (var i = 0; i < TableOfVersions.AmountInfoForVersion[level].Length; i++) // TODO тут нужно использовать сортировку { if (dataLenght < TableOfVersions.AmountInfoForVersion[level][i]) { return(i); } } throw new NullReferenceException("level not exist"); }
/// <summary> /// Method GetCorrectionBlocks creates corrections blocks /// </summary> /// <param name="dataBlocks">blocks containing data</param> /// <param name="correctionLevel">correction level</param> /// <param name="version">version number</param> /// <returns>Returns array containing corrections blocks </returns> internal static byte[][] GetCorrectionBlocks(byte[][] dataBlocks, CorrectionLevel correctionLevel, int version) { byte[][] correctionBlocks; int countBytes = GetCountBytes(correctionLevel, version); byte[] polinomial = polinomials[countBytes]; correctionBlocks = new byte[dataBlocks.Length][]; for (int i = 0; i < correctionBlocks.Length; i++) { correctionBlocks[i] = GetCorrectionBlock(dataBlocks[i], polinomial); } return(correctionBlocks); }
/// <summary> /// Method DivideByBlocks dividing data by blocks /// </summary> /// <param name="data"></param> /// <param name="correctionLevel"></param> /// <param name="version"></param> /// <returns>Returns data divided by blocks</returns> internal static byte[][] DivideByBlocks(byte[] data, CorrectionLevel correctionLevel, int version) { byte[][] dataBlocks; int blocksCount = GetBlocksCount(correctionLevel, version); dataBlocks = new byte[blocksCount][]; int[] blocksLengths = GetBlocksLengths(blocksCount, data.Length); for (int i = 0; i < dataBlocks.Length; i++) { dataBlocks[i] = new byte[blocksLengths[i]]; } dataBlocks = DataCombiner.FillingBlocks(data, dataBlocks); return(dataBlocks); }
private static string ComplementUpToVersion(string str, CorrectionLevel level, int version) { const string first = "11101100"; const string second = "00010001"; var s = new StringBuilder(); var fullBite = TableOfVersions.AmountInfoForVersion[level][version]; var needToComplement = fullBite - str.Length; for (var i = 0; i < needToComplement / 8; i++) { s.Append(i % 2 == 0 ? first : second); } return(str + s); }
private static string Split(string data, CorrectionLevel level, int version, int countOfBlock, int dataInOneBlock, ICollection <DataBlock> list, int k) { for (var i = 0; i < countOfBlock; i++) { list.Add(BlockMaker(data.Substring(0, dataInOneBlock * k), level, version)); if (dataInOneBlock - 1 != data.Length - 1) { data = data.Substring(dataInOneBlock * k - 1, data.Length - dataInOneBlock * k); } else { break; } } return(data); }
private static byte[] Correct(byte[] Block, int Version, CorrectionLevel Level) { int CorrSize = CorrByteCount[(int)Level, Version - 1]; byte[] tmp = new byte[Math.Max(CorrSize, Block.Length)]; Block.CopyTo(tmp, 0); for (int i = Block.Length; i < tmp.Length; i++) { tmp[i] = 0; } for (int cnt = 0; cnt < Block.Length; cnt++) { byte a = tmp[0]; for (int i = 1; i < tmp.Length; i++) { tmp[i - 1] = tmp[i]; } tmp[tmp.Length - 1] = 0; if (a != 0) { byte b = TabGaluaDesc[a]; byte[] g = new byte[CorrSize]; for (int i = 0; i < g.Length; i++) { g[i] = (byte)((Polinom[CorrSize][i] + b) % 255); } for (int i = 0; i < g.Length; i++) { g[i] = TabGalua[g[i]]; } for (int i = 0; i < g.Length; i++) { tmp[i] = (byte)(tmp[i] ^ g[i]); } } } byte[] Result = new byte[CorrSize]; for (int i = 0; i < CorrSize; i++) { Result[i] = tmp[i]; } return(Result); }
private static byte[][] BlockCreate(byte[] Data, int Version, CorrectionLevel Level) { int nBlock = BlockCount[(int)Level, Version - 1]; byte[][] Result = new byte[nBlock][]; int size = Data.Length / nBlock; int md = (Data.Length % nBlock); int ind = 0; for (int i = 0; i < nBlock; i++) { Result[i] = new byte[(i >= nBlock - md ? size + 1 : size)]; for (int j = 0; j < Result[i].Length; j++) { Result[i][j] = Data[ind]; ind++; } } return(Result); }
/// <summary> /// Method GetCapacities returns array of capacities by correction level /// </summary> /// <returns>Return array of capacities</returns> private int[] GetCapacities(CorrectionLevel correctionLevel) { switch (correctionLevel) { case CorrectionLevel.L: return(capacitiesL); case CorrectionLevel.M: return(capacitiesM); case CorrectionLevel.Q: return(capacitiesQ); case CorrectionLevel.H: return(capacitiesH); default: return(default); } }
/// <summary> /// Method GetBlockCount get count of data blocks by correction level /// </summary> /// <param name="correctionLevel"></param> /// <param name="version"></param> /// <returns>Return count of data blocks</returns> private static int GetBlocksCount(CorrectionLevel correctionLevel, int version) { switch (correctionLevel) { case CorrectionLevel.L: return(blocksCountL[version - 1]); case CorrectionLevel.M: return(blocksCountM[version - 1]); case CorrectionLevel.Q: return(blocksCountQ[version - 1]); case CorrectionLevel.H: return(blocksCountH[version - 1]); default: return(default); } }
/// <summary> /// Method GetCountBytes returns count of correction bytes by version /// </summary> /// <param name="correctionLevel">correction level</param> /// <param name="version">version</param> /// <returns>Returns count of correction bytes</returns> private static int GetCountBytes(CorrectionLevel correctionLevel, int version) { switch (correctionLevel) { case CorrectionLevel.L: return(countBytesL[version - 1]); case CorrectionLevel.M: return(countBytesM[version - 1]); case CorrectionLevel.Q: return(countBytesQ[version - 1]); case CorrectionLevel.H: return(countBytesH[version - 1]); default: return(0); } }
private static byte[] DataStream(byte[][] Blocks, int Version, CorrectionLevel Level) { #region Создание блоков коррекции byte[][] CorrBlocks = new byte[Blocks.Length][]; for (int i = 0; i < CorrBlocks.Length; i++) { CorrBlocks[i] = Correct(Blocks[i], Version, Level); } #endregion #region Объединение блоков List <byte> Result = new List <byte>(); int MaxBlock = (from x in Blocks select x.Length).Max(); for (int i = 0; i < MaxBlock; i++) { for (int j = 0; j < Blocks.Length; j++) { if (i < Blocks[j].Length) { Result.Add(Blocks[j][i]); } } } int MaxCorr = (from x in CorrBlocks select x.Length).Max(); for (int i = 0; i < MaxCorr; i++) { for (int j = 0; j < CorrBlocks.Length; j++) { if (i < CorrBlocks[j].Length) { Result.Add(CorrBlocks[j][i]); } } } #endregion return(Result.ToArray()); }
/// <summary> /// Method AddMaskCode adds mask code on the QRCode template /// </summary> /// <param name="template">QR code template</param> /// <param name="correctionLevel">QR code correction level</param> /// <param name="maskId">QR code mask id</param> private void AddMaskCode(byte[,] template, CorrectionLevel correctionLevel, int maskId) { int schemeSize = template.GetLength(0) - 1; int point = 0; byte[] mask; mask = GetMaskCode(correctionLevel, maskId); for (int i = 0; i < 8; i++) { if (i == 6) { point++; } template[8, point] = mask[i]; template[point, 8] = mask[mask.Length - 1 - i]; point++; template[schemeSize - i, 8] = mask[i]; template[8, schemeSize - i] = mask[mask.Length - 1 - i]; } template[schemeSize - 7, 8] = 1; }
/// <summary> /// Method GetMaskCode gets QR code mask as bit sequence /// </summary> /// <param name="correctionLevel">QR code correction level</param> /// <param name="maskId">QR code mask id</param> /// <returns>Returns mask as bit sequence</returns> private byte[] GetMaskCode(CorrectionLevel correctionLevel, int maskId) { if (maskId > 7) { maskId = 0; } switch (correctionLevel) { case CorrectionLevel.L: return(maskCodesL[maskId]); case CorrectionLevel.M: return(maskCodesM[maskId]); case CorrectionLevel.Q: return(maskCodesQ[maskId]); case CorrectionLevel.H: return(maskCodesH[maskId]); default: return(default); } }
public void WriteQR(QRType type, CorrectionLevel correction, string s) { DeedeeDocWriteQR(ptr, (int)type, (int)correction, s); }
public ServiceData(CodingType type, CorrectionLevel level) { CorrectionLevel = level; CodingType = type; }
public Data(string data, CorrectionLevel level, Func <string, string> encode, string codingType) { DataBit = encode(data); Level = level; CodingType = codingType; }
/// <summary> /// Trả về file name (path) của ảnh tạo ra bởi ZXing library (temp file) /// </summary> /// <param name="Text">Văn bản cần sinh mã QR</param> /// <param name="ImageSize">Kích thước của ảnh QR. Tối đa là 500 px</param> /// <param name="Correction">Mức độ chịu lỗi</param> /// <param name="Margin">Số điểm ảnh trắng để làm biên </param> /// <returns></returns> static string GetQRCodeLocalFileNameByZXing(string Text, int ImageSize = 500, CorrectionLevel Correction = CorrectionLevel.High, int Margin = 0) { QRCodeWriter qr = new ZXing.QrCode.QRCodeWriter(); //QRCode as a BitMatrix 2D array Dictionary <EncodeHintType, object> hint = new Dictionary <EncodeHintType, object>(); hint.Add(EncodeHintType.MARGIN, Margin); // margin of the QRCode image hint.Add(EncodeHintType.ERROR_CORRECTION, Correction); var matrix = qr.encode(Text, BarcodeFormat.QR_CODE, ImageSize, ImageSize, hint); // encode QRCode matrix from source text ZXing.BarcodeWriter w = new ZXing.BarcodeWriter(); Bitmap img = w.Write(matrix); // QRCode Bitmap image string tempFile = Path.GetTempFileName(); //create a temp file to save QRCode image img.Save(tempFile, System.Drawing.Imaging.ImageFormat.Png); //save QRCode image to temp file return(tempFile); }
/// <summary> /// Создание QR кода /// </summary> /// <param name="Bytes">Кодируемая последовательность</param> /// <param name="Version">Номер версии (определяет размер)</param> /// <param name="Level">Уровень коррекции</param> /// <param name="MaskCode">Код маски ("-1" - оптимальная)</param> /// <param name="Zoom">Размер квадратиков в пикселах</param> /// <returns>QR код</returns> public static Bitmap CreateQR(byte[] Bytes, int Version, CorrectionLevel Level, int MaskCode, int Zoom) { #region Проверка параметров if (Bytes == null) { throw new ArgumentNullException(ErrorNullData); } if ((Version < 1) || (Version > 40)) { throw new Exception(ErrorBadVersion); } if (((int)Level < 0) || ((int)Level > 3)) { throw new Exception(ErrorBadLevel); } if ((MaskCode < -1) || (MaskCode > 7)) { throw new Exception(ErrorBadMask); } if (Zoom < 1) { throw new Exception(ErrorZoom); } #endregion #region Получение конечного потока данных (byte[] Data) byte[] cBytes = CodingByte(Bytes, Version, Level); byte[][] bData = BlockCreate(cBytes, Version, Level); byte[] Data = DataStream(bData, Version, Level); #endregion #region Выбор маски bool[,] Mtx; if (MaskCode == -1) { Mtx = CreateMatrix(Data, Version, Level, 0); int r = RateMatrix(Mtx); for (int i = 1; i < 8; i++) { bool[,] m = CreateMatrix(Data, Version, Level, i); int n = RateMatrix(m); if (n < r) { Mtx = m; r = n; } } } else { Mtx = CreateMatrix(Data, Version, Level, MaskCode); } #endregion #region Формирование рисунка int BarSize = Mtx.GetLength(0); Bitmap Result = new Bitmap((BarSize + 8) * Zoom, (BarSize + 8) * Zoom); Graphics g = Graphics.FromImage(Result); g.Clear(Color.White); for (int x = 0; x < BarSize; x++) { for (int y = 0; y < BarSize; y++) { g.FillRectangle((Mtx[x, y] ? Brushes.Black : Brushes.White), (4 + x) * Zoom, (4 + y) * Zoom, Zoom, Zoom); } } #endregion return(Result); }
private static bool[,] CreateMatrix(byte[] Data, int Version, CorrectionLevel Level, int MaskCode) { #region Создание матрицы (bool?[,] Mtx) int BarSize = 17 + 4 * Version; bool?[,] Mtx = new bool?[BarSize, BarSize]; for (int i = 0; i < BarSize; i++) { for (int j = 0; j < BarSize; j++) { Mtx[i, j] = null; } } #endregion #region Поисковые узоры void ProcBox(int x, int y, int l, bool f) { for (int i = 0; i < l; i++) { for (int j = 0; j < l; j++) { Mtx[x + i, y + j] = f; } } } #region Большие квадраты void BigBox(int x, int y) { ProcBox(x, y, 7, true); ProcBox(x + 1, y + 1, 5, false); ProcBox(x + 2, y + 2, 3, true); } ProcBox(0, 0, 8, false); BigBox(0, 0); ProcBox(0, BarSize - 8, 8, false); BigBox(0, BarSize - 7); ProcBox(BarSize - 8, 0, 8, false); BigBox(BarSize - 7, 0); #endregion #region Малые квадраты void SmallBox(int x, int y) { ProcBox(x, y, 5, true); ProcBox(x + 1, y + 1, 3, false); ProcBox(x + 2, y + 2, 1, true); } for (int i = 0; i < AlignPosition[Version - 1].Length; i++) { for (int j = 0; j < AlignPosition[Version - 1].Length; j++) { int x = AlignPosition[Version - 1][i]; int y = AlignPosition[Version - 1][j]; if (Mtx[x, y] == null) { SmallBox(x - 2, y - 2); } } } #endregion #region Полоса bool LineFlag = true; for (int i = 6; i < BarSize; i++) { if (Mtx[6, i] == null) { Mtx[6, i] = LineFlag; } if (Mtx[i, 6] == null) { Mtx[i, 6] = LineFlag; } LineFlag = (!LineFlag); } #endregion #endregion #region Код версии if (Version > 6) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 6; j++) { Mtx[j, BarSize - 11 + i] = VersionPattern[Version][i][j]; Mtx[BarSize - 11 + i, j] = VersionPattern[Version][i][j]; } } } #endregion #region Код маски и уровня BitSequence MaskPatt = MaskLevelPattern[MaskCode, (int)Level]; Mtx[0, 8] = MaskPatt[0]; Mtx[1, 8] = MaskPatt[1]; Mtx[2, 8] = MaskPatt[2]; Mtx[3, 8] = MaskPatt[3]; Mtx[4, 8] = MaskPatt[4]; Mtx[5, 8] = MaskPatt[5]; Mtx[7, 8] = MaskPatt[6]; Mtx[8, 8] = MaskPatt[7]; Mtx[8, 7] = MaskPatt[8]; Mtx[8, 5] = MaskPatt[9]; Mtx[8, 4] = MaskPatt[10]; Mtx[8, 3] = MaskPatt[11]; Mtx[8, 2] = MaskPatt[12]; Mtx[8, 1] = MaskPatt[13]; Mtx[8, 0] = MaskPatt[14]; Mtx[8, BarSize - 1] = MaskPatt[0]; Mtx[8, BarSize - 2] = MaskPatt[1]; Mtx[8, BarSize - 3] = MaskPatt[2]; Mtx[8, BarSize - 4] = MaskPatt[3]; Mtx[8, BarSize - 5] = MaskPatt[4]; Mtx[8, BarSize - 6] = MaskPatt[5]; Mtx[8, BarSize - 7] = MaskPatt[6]; Mtx[8, BarSize - 8] = true; Mtx[BarSize - 8, 8] = MaskPatt[7]; Mtx[BarSize - 7, 8] = MaskPatt[8]; Mtx[BarSize - 6, 8] = MaskPatt[9]; Mtx[BarSize - 5, 8] = MaskPatt[10]; Mtx[BarSize - 4, 8] = MaskPatt[11]; Mtx[BarSize - 3, 8] = MaskPatt[12]; Mtx[BarSize - 2, 8] = MaskPatt[13]; Mtx[BarSize - 1, 8] = MaskPatt[14]; #endregion #region Запись данных BitSequence stm = new BitSequence(Data); int xx = BarSize - 1; int yy = BarSize - 1; bool dx = false; int dy = -1; for (int n = 0; n < stm.Length; n++) { #region Выбор следующей ячейки while (Mtx[xx, yy] != null) { if (xx == 6) { xx--; continue; } if (!dx) { xx--; dx = (!dx); continue; } if ((yy + dy >= 0) && (yy + dy <= BarSize - 1)) { xx++; yy += dy; dx = (!dx); continue; } xx--; dx = (!dx); dy = -dy; } #endregion Mtx[xx, yy] = (stm[n] ^ MaskFunction[MaskCode](xx, yy)); } #endregion #region Дозаполнение пустого места for (int i = 0; i < BarSize; i++) { for (int j = 0; j < BarSize; j++) { if (Mtx[i, j] == null) { Mtx[i, j] = MaskFunction[MaskCode](i + 1, j + 1); } } } #endregion #region Формирование результата bool[,] Result = new bool[BarSize, BarSize]; for (int i = 0; i < BarSize; i++) { for (int j = 0; j < BarSize; j++) { Result[i, j] = (bool)Mtx[i, j]; } } #endregion return(Result); }
public DataBlock(List <int> data, CorrectionLevel level, int version) { Data = data; CountOfCorrectionBytes = GetCount(level, version); }
private static int GetCount(CorrectionLevel level, int version) { return(TableCorrectionBytes.BytesMap[level][version]); }
public QRTemplater(CorrectionLevel correctionLevel, int version) { CorrectionLevel = correctionLevel; Version = version; }
/// <summary> /// Trả về file name (path) của ảnh tạo ra bởi ZXing library (temp file) /// </summary> /// <param name="Text">Văn bản cần sinh mã QR</param> /// <param name="ImageSize">Kích thước của ảnh QR. Tối đa là 500 px</param> /// <param name="Correction">Mức độ chịu lỗi</param> /// <param name="Margin">Số điểm ảnh trắng để làm biên </param> /// <returns></returns> static string GetQRCodeLocalFileNameByZXing(string Text, int ImageSize = 500, CorrectionLevel Correction = CorrectionLevel.High, int Margin = 0) { QRCodeWriter qr = new ZXing.QrCode.QRCodeWriter(); //QRCode as a BitMatrix 2D array Dictionary <EncodeHintType, object> hint = new Dictionary <EncodeHintType, object>(); hint.Add(EncodeHintType.MARGIN, Margin); // margin of the QRCode image hint.Add(EncodeHintType.ERROR_CORRECTION, Correction); var matrix = qr.encode(Text, BarcodeFormat.QR_CODE, ImageSize, ImageSize, hint); // encode QRCode matrix from source text ZXing.BarcodeWriter w = new ZXing.BarcodeWriter(); Bitmap img = w.Write(matrix); // QRCode Bitmap image string tempFile = Path.GetTempFileName(); //create a temp file to save QRCode image img.Save(tempFile, System.Drawing.Imaging.ImageFormat.Png); //save QRCode image to temp file //old one - use clipboard //MemoryStream ms = new MemoryStream(); //img.Save(ms, System.Drawing.Imaging.ImageFormat.Png); //save QRCode image to memory stream //System.Drawing.Image i = System.Drawing.Image.FromStream(ms); // create image in Image form //Clipboard.SetDataObject(i);// set image to clipboard return(tempFile); }