You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.8 KiB

  1. #if NET40 || NET461
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. namespace Apewer.Internals.QrCode
  6. {
  7. // ReSharper disable once InconsistentNaming
  8. internal class BitmapByteQRCode : AbstractQRCode, IDisposable
  9. {
  10. /// <summary>
  11. /// Constructor without params to be used in COM Objects connections
  12. /// </summary>
  13. public BitmapByteQRCode() { }
  14. public BitmapByteQRCode(QRCodeData data) : base(data) { }
  15. public byte[] GetGraphic(int pixelsPerModule)
  16. {
  17. return GetGraphic(pixelsPerModule, new byte[] { 0x00, 0x00, 0x00 }, new byte[] { 0xFF, 0xFF, 0xFF });
  18. }
  19. public byte[] GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex)
  20. {
  21. return GetGraphic(pixelsPerModule, HexColorToByteArray(darkColorHtmlHex), HexColorToByteArray(lightColorHtmlHex));
  22. }
  23. private static byte[] Reverse(byte[] input)
  24. {
  25. if (input == null) return null;
  26. var length = input.Length;
  27. var output = new byte[length];
  28. for (var i = 0; i < length; i++)
  29. {
  30. output[i] = input[length - i - 1];
  31. }
  32. return output;
  33. }
  34. public byte[] GetGraphic(int pixelsPerModule, byte[] darkColorRgb, byte[] lightColorRgb)
  35. {
  36. var sideLength = this.QrCodeData.ModuleMatrix.Count * pixelsPerModule;
  37. var moduleDark = Reverse(darkColorRgb);
  38. var moduleLight = Reverse(lightColorRgb);
  39. List<byte> bmp = new List<byte>();
  40. //header
  41. bmp.AddRange(new byte[] { 0x42, 0x4D, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00 });
  42. //width
  43. bmp.AddRange(IntTo4Byte(sideLength));
  44. //height
  45. bmp.AddRange(IntTo4Byte(sideLength));
  46. //header end
  47. bmp.AddRange(new byte[] { 0x01, 0x00, 0x18, 0x00 });
  48. //draw qr code
  49. for (var x = sideLength - 1; x >= 0; x = x - pixelsPerModule)
  50. {
  51. for (int pm = 0; pm < pixelsPerModule; pm++)
  52. {
  53. for (var y = 0; y < sideLength; y = y + pixelsPerModule)
  54. {
  55. var module =
  56. this.QrCodeData.ModuleMatrix[(x + pixelsPerModule) / pixelsPerModule - 1][(y + pixelsPerModule) / pixelsPerModule - 1];
  57. for (int i = 0; i < pixelsPerModule; i++)
  58. {
  59. bmp.AddRange(module ? moduleDark : moduleLight);
  60. }
  61. }
  62. if (sideLength % 4 != 0)
  63. {
  64. for (int i = 0; i < sideLength % 4; i++)
  65. {
  66. bmp.Add(0x00);
  67. }
  68. }
  69. }
  70. }
  71. //finalize with terminator
  72. bmp.AddRange(new byte[] { 0x00, 0x00 });
  73. return bmp.ToArray();
  74. }
  75. private byte[] HexColorToByteArray(string colorString)
  76. {
  77. if (colorString.StartsWith("#"))
  78. colorString = colorString.Substring(1);
  79. byte[] byteColor = new byte[colorString.Length / 2];
  80. for (int i = 0; i < byteColor.Length; i++)
  81. byteColor[i] = byte.Parse(colorString.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture);
  82. return byteColor;
  83. }
  84. private byte[] IntTo4Byte(int inp)
  85. {
  86. byte[] bytes = new byte[2];
  87. unchecked
  88. {
  89. bytes[1] = (byte)(inp >> 8);
  90. bytes[0] = (byte)(inp);
  91. }
  92. return bytes;
  93. }
  94. }
  95. }
  96. #endif