diff --git a/.gitignore b/.gitignore index f3bf957f..0276e92c 100644 --- a/.gitignore +++ b/.gitignore @@ -218,3 +218,4 @@ pip-log.txt # Xamarin *.userprefs +QRCoder/PortabilityAnalysis.html diff --git a/MyGet.bat b/MyGet.bat index c13f2076..e581e1a4 100644 --- a/MyGet.bat +++ b/MyGet.bat @@ -14,5 +14,6 @@ if not "%PackageVersion%" == "" ( mkdir Build mkdir Build\lib mkdir Build\lib\net40 +mkdir Build\lib\netcore45 %NuGet% pack "QRCoder\QRCoder.nuspec" -NoPackageAnalysis -verbosity detailed -o Build -Version %version% -p Configuration="%config%" diff --git a/QRCoder/BitmapByteQRCode.cs b/QRCoder/BitmapByteQRCode.cs new file mode 100644 index 00000000..1bb0d68d --- /dev/null +++ b/QRCoder/BitmapByteQRCode.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QRCoder +{ + + // ReSharper disable once InconsistentNaming + public class BitmapByteQRCode : AbstractQRCode, IDisposable + { + public BitmapByteQRCode(QRCodeData data) : base(data) { } + + + public override byte[] GetGraphic(int pixelsPerModule) + { + var sideLength = this.QrCodeData.ModuleMatrix.Count * pixelsPerModule; + + var moduleDark = new byte[] {0x00, 0x00, 0x00}; + var moduleLight = new byte[] { 0xFF, 0xFF, 0xFF}; + + List bmp = new List(); + + //header + bmp.AddRange(new byte[] { 0x42, 0x4D, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00 }); + + //width + bmp.AddRange(IntTo4Byte(sideLength)); + //height + bmp.AddRange(IntTo4Byte(sideLength)); + + //header end + bmp.AddRange(new byte[] { 0x01, 0x00, 0x18, 0x00 }); + + //draw qr code + for (var x = sideLength-1; x >= 0; x = x - pixelsPerModule) + { + for (int pm = 0; pm < pixelsPerModule; pm++) + { + for (var y = 0; y < sideLength; y = y + pixelsPerModule) + { + var module = + this.QrCodeData.ModuleMatrix[(x + pixelsPerModule)/pixelsPerModule - 1][(y + pixelsPerModule)/pixelsPerModule - 1]; + for (int i = 0; i < pixelsPerModule; i++) + { + bmp.AddRange(module ? moduleDark : moduleLight); + } + } + if (sideLength%4 != 0) + { + for (int i = 0; i < sideLength%4; i++) + { + bmp.Add(0x00); + } + } + } + } + + //finalize with terminator + bmp.AddRange(new byte[] { 0x00, 0x00 }); + + return bmp.ToArray(); + } + private byte[] IntTo4Byte(int inp) + { + byte[] bytes = new byte[2]; + unchecked + { + bytes[1] = (byte)(inp >> 8); + bytes[0] = (byte)(inp); + } + return bytes; + } + + public void Dispose() + { + this.QrCodeData = null; + } + } +} diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs index 5a7917ed..f08003b9 100644 --- a/QRCoder/QRCodeGenerator.cs +++ b/QRCoder/QRCodeGenerator.cs @@ -4,6 +4,7 @@ using System.Text; using System.Collections; using System.Reflection; +using System.Runtime.InteropServices; namespace QRCoder { @@ -207,10 +208,22 @@ public static void AddQuietZone(ref QRCodeData qrCode) } } + private static string ReverseString(string inp) + { + string newStr = string.Empty; + if (inp.Length > 0) + { + for (int i = inp.Length - 1; i >= 0; i--) + newStr += inp[i]; + } + return newStr; + } + public static void PlaceVersion(ref QRCodeData qrCode, string versionStr) { var size = qrCode.ModuleMatrix.Count; - var vStr = new string(versionStr.Reverse().ToArray()); + + var vStr = ReverseString(versionStr); for (var x = 0; x < 6; x++) { @@ -225,7 +238,7 @@ public static void PlaceVersion(ref QRCodeData qrCode, string versionStr) public static void PlaceFormat(ref QRCodeData qrCode, string formatStr) { var size = qrCode.ModuleMatrix.Count; - var fStr = new string(formatStr.Reverse().ToArray()); + var fStr = ReverseString(formatStr); var modules = new[,] { { 8, 0, size - 1, 8 }, { 8, 1, size - 2, 8 }, { 8, 2, size - 3, 8 }, { 8, 3, size - 4, 8 }, { 8, 4, size - 5, 8 }, { 8, 5, size - 6, 8 }, { 8, 7, size - 7, 8 }, { 8, 8, size - 8, 8 }, { 7, 8, 8, size - 7 }, { 5, 8, 8, size - 6 }, { 4, 8, 8, size - 5 }, { 3, 8, 8, size - 4 }, { 2, 8, 8, size - 3 }, { 1, 8, 8, size - 2 }, { 0, 8, 8, size - 1 } }; for (var i = 0; i < 15; i++) { @@ -235,6 +248,7 @@ public static void PlaceFormat(ref QRCodeData qrCode, string formatStr) qrCode.ModuleMatrix[p2.Y][p2.X] = fStr[i] == '1'; } } + public static int MaskCode(ref QRCodeData qrCode, int version, ref List blockedModules, ECCLevel eccLevel) { @@ -243,7 +257,14 @@ public static int MaskCode(ref QRCodeData qrCode, int version, ref List x.Name == patternName); + + + #if NET40 + var patterMethod = typeof(MaskPattern).GetMethods().First(x => x.Name == patternName); + #else + var patterMethod = typeof(MaskPattern).GetTypeInfo().GetDeclaredMethod(patternName); + #endif + + for (var x = 0; x < size; x++) { for (var y = 0; y < size; y++) @@ -306,7 +335,10 @@ public static void PlaceDataWords(ref QRCodeData qrCode, string data, ref List(); - data.ToList().ForEach(x => datawords.Enqueue(x != '0')); + for (int i = 0; i< data.Length; i++) + { + datawords.Enqueue(data[i] != '0'); + } for (var x = size - 1; x >= 0; x = x - 2) { if (x == 6) @@ -701,14 +733,29 @@ private int GetVersion(int length, EncodingMode encMode, ECCLevel eccLevel) private EncodingMode GetEncodingFromPlaintext(string plainText) { - if (plainText.All(c => "0123456789".Contains(c))) + if (StringAll(plainText, "0123456789")) return EncodingMode.Numeric; - else if (plainText.All(c => this.alphanumEncTable.Contains(c))) + else if (StringAll(plainText, this.alphanumEncTable.ToString())) return EncodingMode.Alphanumeric; else return EncodingMode.Byte; } + private bool StringAll(string input, string charGroupIn) + { + + bool res = true; + foreach (var c in input) + { + if (!charGroupIn.Contains(c.ToString())) + { + res = false; + break; + } + } + return res; + } + private Polynom CalculateMessagePolynom(string bitString) { var messagePol = new Polynom(); @@ -743,8 +790,8 @@ private Polynom CalculateGeneratorPolynom(int numEccWords) } private List BinaryStringToBitBlockList(string bitString) - { - return bitString.ToList().Select((x, i) => new { Index = i, Value = x }) + { + return new List(bitString.ToCharArray()).Select((x, i) => new { Index = i, Value = x }) .GroupBy(x => x.Index / 8) .Select(x => String.Join("", x.Select(v => v.Value.ToString()).ToArray())) .ToList(); @@ -819,7 +866,8 @@ private bool IsUtf8(EncodingMode encoding, string plainText) private bool IsValidISO(string input) { var bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(input); - var result = Encoding.GetEncoding("ISO-8859-1").GetString(bytes); + //var result = Encoding.GetEncoding("ISO-8859-1").GetString(bytes); + var result = Encoding.GetEncoding("ISO-8859-1").GetString(bytes,0,bytes.Length); return String.Equals(input, result); } @@ -990,7 +1038,12 @@ private static int ShrinkAlphaExp(int alphaExp) private void CreateAlphanumEncDict() { this.alphanumEncDict = new Dictionary(); - this.alphanumEncTable.ToList().Select((x, i) => new { Chr = x, Index = i }).ToList().ForEach(x => this.alphanumEncDict.Add(x.Chr, x.Index)); + //this.alphanumEncTable.ToList().Select((x, i) => new { Chr = x, Index = i }).ToList().ForEach(x => this.alphanumEncDict.Add(x.Chr, x.Index)); + var resList = this.alphanumEncTable.ToList().Select((x, i) => new { Chr = x, Index = i }).ToList(); + foreach (var res in resList) + { + this.alphanumEncDict.Add(res.Chr, res.Index); + } } private void CreateAlignmentPatternTable() @@ -1279,7 +1332,11 @@ public Polynom() public override string ToString() { var sb = new StringBuilder(); - this.PolyItems.ForEach(x => sb.Append("a^" + x.Coefficient + "*x^" + x.Exponent + " + ")); + //this.PolyItems.ForEach(x => sb.Append("a^" + x.Coefficient + "*x^" + x.Exponent + " + ")); + foreach (var polyItem in this.PolyItems) + { + sb.Append("a^" + polyItem.Coefficient + "*x^" + polyItem.Exponent + " + "); + } return sb.ToString().TrimEnd(new[] { ' ', '+' }); } diff --git a/QRCoder/QRCoder.csproj b/QRCoder/QRCoder.csproj index 30c0866a..92ca1cff 100644 --- a/QRCoder/QRCoder.csproj +++ b/QRCoder/QRCoder.csproj @@ -17,9 +17,10 @@ full false bin\Debug\ - DEBUG;TRACE + TRACE;DEBUG;NET40 prompt 4 + false pdbonly @@ -28,6 +29,7 @@ TRACE prompt 4 + false @@ -46,6 +48,7 @@ + diff --git a/QRCoder/QRCoderProject.Portable.csproj b/QRCoder/QRCoderProject.Portable.csproj new file mode 100644 index 00000000..252ddfe3 --- /dev/null +++ b/QRCoder/QRCoderProject.Portable.csproj @@ -0,0 +1,56 @@ + + + + + 10.0 + Debug + AnyCPU + {B2709734-9F32-4750-9CEC-10C5915B23FB} + Library + Properties + QRCoder + QRCoder + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile111 + v4.5 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/QRCoderDemoUWP/App.xaml b/QRCoderDemoUWP/App.xaml new file mode 100644 index 00000000..ebae4611 --- /dev/null +++ b/QRCoderDemoUWP/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/QRCoderDemoUWP/App.xaml.cs b/QRCoderDemoUWP/App.xaml.cs new file mode 100644 index 00000000..2c90273f --- /dev/null +++ b/QRCoderDemoUWP/App.xaml.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +namespace QRCoderDemoUWP +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App : Application + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + this.Suspending += OnSuspending; + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs e) + { +#if DEBUG + if (System.Diagnostics.Debugger.IsAttached) + { + this.DebugSettings.EnableFrameRateCounter = true; + } +#endif + Frame rootFrame = Window.Current.Content as Frame; + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == null) + { + // Create a Frame to act as the navigation context and navigate to the first page + rootFrame = new Frame(); + + rootFrame.NavigationFailed += OnNavigationFailed; + + if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + //TODO: Load state from previously suspended application + } + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + } + + if (e.PrelaunchActivated == false) + { + if (rootFrame.Content == null) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame.Navigate(typeof(MainPage), e.Arguments); + } + // Ensure the current window is active + Window.Current.Activate(); + } + } + + /// + /// Invoked when Navigation to a certain page fails + /// + /// The Frame which failed navigation + /// Details about the navigation failure + void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + } + + /// + /// Invoked when application execution is being suspended. Application state is saved + /// without knowing whether the application will be terminated or resumed with the contents + /// of memory still intact. + /// + /// The source of the suspend request. + /// Details about the suspend request. + private void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + //TODO: Save application state and stop any background activity + deferral.Complete(); + } + } +} diff --git a/QRCoderDemoUWP/Assets/LockScreenLogo.scale-200.png b/QRCoderDemoUWP/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 00000000..735f57ad Binary files /dev/null and b/QRCoderDemoUWP/Assets/LockScreenLogo.scale-200.png differ diff --git a/QRCoderDemoUWP/Assets/SplashScreen.scale-200.png b/QRCoderDemoUWP/Assets/SplashScreen.scale-200.png new file mode 100644 index 00000000..023e7f1f Binary files /dev/null and b/QRCoderDemoUWP/Assets/SplashScreen.scale-200.png differ diff --git a/QRCoderDemoUWP/Assets/Square150x150Logo.scale-200.png b/QRCoderDemoUWP/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 00000000..af49fec1 Binary files /dev/null and b/QRCoderDemoUWP/Assets/Square150x150Logo.scale-200.png differ diff --git a/QRCoderDemoUWP/Assets/Square44x44Logo.scale-200.png b/QRCoderDemoUWP/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 00000000..ce342a2e Binary files /dev/null and b/QRCoderDemoUWP/Assets/Square44x44Logo.scale-200.png differ diff --git a/QRCoderDemoUWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/QRCoderDemoUWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 00000000..f6c02ce9 Binary files /dev/null and b/QRCoderDemoUWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/QRCoderDemoUWP/Assets/StoreLogo.png b/QRCoderDemoUWP/Assets/StoreLogo.png new file mode 100644 index 00000000..7385b56c Binary files /dev/null and b/QRCoderDemoUWP/Assets/StoreLogo.png differ diff --git a/QRCoderDemoUWP/Assets/Wide310x150Logo.scale-200.png b/QRCoderDemoUWP/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 00000000..288995b3 Binary files /dev/null and b/QRCoderDemoUWP/Assets/Wide310x150Logo.scale-200.png differ diff --git a/QRCoderDemoUWP/MainPage.xaml b/QRCoderDemoUWP/MainPage.xaml new file mode 100644 index 00000000..38550d41 --- /dev/null +++ b/QRCoderDemoUWP/MainPage.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + +