C#利用QrCode.Net生成二维码
现在网上很多应用都是用二维码来分享网址或者其它的信息。尤其在移动领域,二维码更是有很大的应用场景。
因为项目的需要,需要在网站中增加一个生成二维码分析网址的功能,在谷歌大幅度抽筋的情况下无奈使用百度。百度N多,找到一些项目,但是可用性不强。(有一个项目是用VS2005开发的,在2010中调试不开。)终于在codeplex上找到一个“神器”,这个“神器”可以很方便的生成二维码,速度那是相当的快,并且可支持中文,遵从MIT协议。
QrCode.Net是一个使用C#编写的用于生成二维码图片的类库,使用它可以非常方便的为WinForm、WebForm、WPF、Silverlight和Windows Phone 7应用程序提供二维码编码输出功能。可以将二维码文件导出为eps格式。
项目地址为:http://qrcodenet.codeplex.com
QrCode.Net不再采用http://code.google.com/p/zxing/ ZXing的端口,新的版本将有更好的性能。
测试结果如下(微秒):
输入字符串长度:74个
EC performance 1000 Tests~ QrCode.Net: 3929 ZXing: 5221
同时,QrCode.Net可以对字符串进行分析,决定是否使用UTF-8编码。(比如使用中文的时候。)
QrCode使用方法:
新建项目添加对类库的引用,或者也可以通过Nuget中搜索QrCode.Net进行引用,然后在使用的类上引入Gma.QrCodeNet.Encoding命名空间。
using Gma.QrCodeNet.Encoding; |
在控制台中输出二维码:
Console.Write( @"Type some text to QR code: " ); string sampleText = Console.ReadLine(); QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.M); QrCode qrCode = qrEncoder.Encode(sampleText); for ( int j = 0; j < qrCode.Matrix.Width; j++) { for ( int i = 0; i < qrCode.Matrix.Width; i++) { char charToPrint = qrCode.Matrix[i, j] ? '█' : ' ' ; Console.Write(charToPrint); } Console.WriteLine(); } Console.WriteLine( @"Press any key to quit." ); Console.ReadKey(); |
此代码将产生以下输出:
上面的代码在控制台中输出的时候不是连续的,无法通过扫描二维码进行解析出来,稍微修改了一下代码,改用控制台背景色来代表黑白字符(其他颜色根据自己喜好修改吧)
static void Main(string[] args) { Console.WriteLine(@"Type some text to QR code: "); string sampleText = Console.ReadLine(); QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.M); QrCode qrCode = qrEncoder.Encode(sampleText); Console.BackgroundColor = ConsoleColor.White; for (int i = 0; i < qrCode.Matrix.Width + 2; i++) Console.Write(" ");//中文全角的空格符 Console.WriteLine(); for (int j = 0; j < qrCode.Matrix.Height; j++) { for (int i = 0; i < qrCode.Matrix.Width; i++) { //char charToPoint = qrCode.Matrix[i, j] ? '█' : ' '; Console.Write(i == 0 ? " " : "");//中文全角的空格符 Console.BackgroundColor = qrCode.Matrix[i, j] ? ConsoleColor.Black : ConsoleColor.White; Console.Write(' ');//中文全角的空格符 Console.BackgroundColor = ConsoleColor.White; Console.Write(i == qrCode.Matrix.Width - 1 ? " " : "");//中文全角的空格符 } Console.WriteLine(); } for (int i = 0; i < qrCode.Matrix.Width + 2; i++) Console.Write(" ");//中文全角的空格符 Console.BackgroundColor = ConsoleColor.Black; Console.WriteLine(); Console.WriteLine(@"Press any key to quit."); Console.ReadKey(); }
结果如下:
在Graphics上绘制二维码:
const string helloWorld = "Hello World!" ; QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H); QrCode qrCode = qrEncoder.Encode(helloWorld); const int moduleSizeInPixels = 5; Renderer renderer = new Renderer(moduleSizeInPixels, Brushes.Black, Brushes.White); Panel panel = new Panel(); Point padding = new Point(10,16); Size qrCodeSize = renderer.Measure(qrCode.Matrix.Width); panel.AutoSize = false ; panel.Size = qrCodeSize + new Size(2 * padding.X, 2 * padding.Y); using (Graphics graphics = panel.CreateGraphics()) { renderer.Draw(graphics, qrCode.Matrix, padding); } |
在WriteableBitmap上绘制二维码:
const string helloWorld = "Hello World!" ; QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H); QrCode qrCode = new QrCode(); qrEncoder.TryEncode(helloWorld, out qrCode); const int moduleSizeInPixels = 5; Renderer renderer = new Renderer(moduleSizeInPixels); //Black&White is default colour for drawing QrCode //Matrix under qrCode might be null if input string is null or empty. 21 module wide is version 1 QrCode's width. int pixelSize = qrCode.Matrix == null ? renderer.Measure(21) : renderer.Measure(qrCode.Matrix.Width); WriteableBitmap wBitmap = new WriteableBitmap(pixelSize, pixelSize, 96, 96, PixelFormats.Gray8, null ); //If wBitmap is null value. renderer will create Gray8 Bitmap as default. renderer.Draw(wBitmap, qrCode.Matrix); //Default offset position is (0, 0); //Now you can put wBitmap to Image control's Source or use it to create image file. |
如果需要把二维码呈现在WinForm或者WPF应用程序中,可以直接把类库拖入工具箱,然后直接在窗体上拖出控件。
直接把二维码保存到文件:
QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H); QrCode qrCode = new QrCode(); qrEncoder.TryEncode(helloWorld, out qrCode); Renderer renderer = new Renderer(5, Brushes.Black, Brushes.White); renderer.CreateImageFile(qrCode.Matrix, @"c:\temp\HelloWorld.png" , ImageFormat.Png); |
将二维码写入Stream:
QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H); QrCode qrCode = new QrCode(); qrEncoder.TryEncode(helloWorld, out qrCode); Renderer renderer = new Renderer(5, Brushes.Black, Brushes.White); MemoryStream ms = new MemoryStream(); renderer.WriteToStream(qrCode.Matrix, ms, ImageFormat.png); |
出处:https://www.cnblogs.com/Soar1991/archive/2012/03/30/2426115.html
=======================================================================================
艺术二维码素材生成器
最近公司让我开发一个条形码的生成控件,花了半天时间搞定觉得不过瘾,什么年代了该用二维码了吧。于是wiki了一下二维码的资料。
比较常见的就是QR码(Quick Response)即快速识别码,为了验证“快速”,我特地和条形码做了一次比较:经过我测试条形码的code 128编码方式可以表示数字、字母、和符号,而且长度也可以很长。当我用“我查查”进行识别测试时发现,当长度达到20个字符时就很难识别出来了,速度也比较慢,也许是软件的原因吧。但二维码不同,其中包括了汉字等乱七八糟的一大堆东西,同样可以秒识。
看了各种外国设计师的艺术二维码设计让我一发不可收拾。先来欣赏一下国外大师的设计吧:
这里选了几张个人比较喜欢,比较有代表性的。
1.总体思路
这是一张普通的二维码:
我们可以把它看作由很多正方形组成的矩阵,每一个正方形就是矩阵中的一个节点。那3个大方框和右下角的小方框是用来定位二维码的方向位置的。
先排除颜色贴图不管,那些艺术二维码的区别无非就是节点的形状不同而已,有方的、圆的、还有在方的边缘做了平滑处理的。如果能用这些节点生成最基本的黑白原型,用PS加上颜色和贴图简直就是轻而易举。所以我做了这个一个快速原型工具,如下图:
通过修改左边的参数就可以实现各种效果:
改变节点大小
使用随机节点大小和随机颜色
圆形节点
圆形随机大小、随机颜色
自定义形状节点
生成各种素材,经过PS的拼装处理,基本可以实现任何效果了。
(有些比较难识别,是因为比较难找到作为位置定位的那几个方框,所以还得PS处理时,要把那几个方框做得明显些)
关于方形边缘平滑处理效果,由于用PS比较容易实现,就懒得研究代码了,录制个PS动作更快些。如下:
这个是女朋友生日那天临时设计的。
2.详细设计
关于二维码的生成这里我用了一个开源项目QrCode.Net(http://qrcodenet.codeplex.com/)其实这个工程里面已经自带了WPF的控件,可以生成最基本的正方形节点二维码,且有一个属性是Path的材质,这样生成普通的二维码已经方便了,但是不能满足我们多样化的需求。
所以,我只用到了他生成一个二维数组来表示二维码的算法,二维数组的元素只有0和1,其中0表示没有黑块,1表示有,这样只要根据自定义路径的大小计算出每个块的位置,用代码布局一下就出来了。
我自己写了一个可以用任意形状路径填充节点的类,并增加随机节点大小和随机颜色功能,而且修复了它的一些Bug,这样即满足了多样化的需求,而且整个二维码都是用路径来表示,换句话说就是矢量图,这样就可以生成任意大小的图片,满足各种用途。
原本的这个开源项目可以导出.eps矢量格式,可供Adobe Illustrator 使用,而Adobe Illustrator的标准格式.AI,可以被Expression Design 4导入,Expression Design 4又可以转换为XAML文件,也就是说这么多软件都可以用来加工我们的二维码原型,这样就增加了设计的可能性。但是当我看完它转换的实现源码时,我愣住了,完全由作者自己写的代码,只是在做字符串的拼接,形成.eps的格式,而且只考虑到了直线路径...所以我就只能将矢量图输出为位图来保存(这里保存为.png格式,因为png是无损压缩格式,作为中介不错)通过PS加工,好在分辨率基本可以满足大部分需求了。为什么Expression Design 4不能导入XAML格式啊....
由于代码比较多,思路我上面已经说明了,只是编码的问题了,这里我就贴出源码,感兴趣的可以自己研究一下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Gma.QrCodeNet.Encoding; using Gma.QrCodeNet.Encoding.Windows.Render; using System.Windows; using System.Windows.Controls; namespace QRCodeFactory { static class PathRender { /// <summary> /// 以矩形来填充矩阵点 /// </summary> /// <param name="QrMatrix">算出来的矩阵</param> /// <param name="xScale">isRandom?随机取值的最小值:每个点的宽度</param> /// <param name="yScale">isRandom?随机取值的最大值:每个点的高度</param> /// <param name="isRandom">是否随机大小</param> /// <returns>返回路径填充材质</returns> public static StreamGeometry DrawRectGeometry(BitMatrix QrMatrix, double xScale, double yScale, bool isRandom) { int width = QrMatrix == null ? 21 : QrMatrix.Width; StreamGeometry qrCodeStream = new StreamGeometry(); qrCodeStream.FillRule = FillRule.EvenOdd; if (QrMatrix == null) return qrCodeStream; using (StreamGeometryContext qrCodeCtx = qrCodeStream.Open()) { for (int y = 0; y < width; y++) { for (int x = 0; x < width; x++) { if (QrMatrix[x, y]) { if (isRandom) qrCodeCtx.DrawRectGeometry(x, y, (double)(new Random(x + y + Environment.TickCount).Next((int)(xScale * 100), (int)(yScale * 100))) / 100, (double)(new Random(x + y + Environment.TickCount).Next((int)(xScale * 100), (int)(yScale * 100))) / 100); else qrCodeCtx.DrawRectGeometry(x, y, xScale, yScale); } } } } qrCodeStream.Freeze(); return qrCodeStream; } /// <summary> /// 以圆点来填充矩阵点 /// </summary> /// <param name="QrMatrix">算出来的矩阵</param> /// <param name="xScale">isRandom?随机取值的最小值:每个点的宽度</param> /// <param name="yScale">isRandom?随机取值的最大值:每个点的高度</param> /// <param name="isRandom">是否随机大小</param> /// <returns>返回路径填充材质</returns> public static StreamGeometry DrawEllipseGeometry(BitMatrix QrMatrix, double xScale, double yScale, bool isRandom) { int width = QrMatrix == null ? 21 : QrMatrix.Width; StreamGeometry qrCodeStream = new StreamGeometry(); qrCodeStream.FillRule = FillRule.EvenOdd; if (QrMatrix == null) return qrCodeStream; using (StreamGeometryContext qrCodeCtx = qrCodeStream.Open()) { for (int y = 0; y < width; y++) { for (int x = 0; x < width; x++) { if (QrMatrix[x, y]) { if (isRandom) qrCodeCtx.DrawEllipseGeometry(x, y, (double)(new Random(x + y + Environment.TickCount).Next((int)(xScale * 100), (int)(yScale * 100))) / 100, (double)(new Random(x + y + Environment.TickCount).Next((int)(xScale * 100), (int)(yScale * 100))) / 100); else qrCodeCtx.DrawEllipseGeometry(x, y, xScale, yScale); } } } } qrCodeStream.Freeze(); return qrCodeStream; } /// <summary> /// 以自定义图形来填充矩阵点 /// </summary> /// <param name="QrMatrix">算出来的矩阵</param> /// <param name="xScale">isRandom?随机取值的最小值:每个点的宽度</param> /// <param name="yScale">isRandom?随机取值的最大值:每个点的高度</param> /// <param name="isRandomSize">是否随机大小</param> /// <returns>返回路径填充材质</returns> public static void DrawCustomGeometry(BitMatrix QrMatrix, ref Grid drawGrid, Path pathGeo, double xScale, double yScale, bool isRandomSize,bool isRandomColor) { int width = QrMatrix == null ? 21 : QrMatrix.Width; drawGrid.Width = drawGrid.Height = width * pathGeo.Width; for (int y = 0; y < width; y++) { for (int x = 0; x < width; x++) { if (QrMatrix[x, y]) { Path newPath = new Path();//创建一个路径,代表一点 newPath.StrokeThickness = 0; newPath.Stretch = Stretch.UniformToFill;//填充方式s newPath.HorizontalAlignment = HorizontalAlignment.Left; newPath.VerticalAlignment = VerticalAlignment.Top; newPath.Data = pathGeo.Data; newPath.RenderTransformOrigin = new Point(0.5, 0.5); TranslateTransform newTTF = new TranslateTransform(x * pathGeo.Width, y * pathGeo.Height); newPath.RenderTransform = newTTF; if (isRandomSize)//如果随机大小 { newPath.Width = newPath.Height = pathGeo.Width * (double)(new Random(x + y + Environment.TickCount).Next((int)(xScale * 100), (int)(yScale * 100))) / 100; } else { newPath.Width = pathGeo.Width * xScale; newPath.Height = pathGeo.Height * yScale; } if (isRandomColor)//如果随机颜色 newPath.Fill = new SolidColorBrush(GetRandomColor()); else newPath.Fill = Brushes.Black; drawGrid.Children.Add(newPath); } } } } internal static void DrawRectGeometry(this StreamGeometryContext ctx, double X, double Y, double Width, double Height) { ctx.BeginFigure(new Point(X, Y),true, true); ctx.LineTo(new Point(X, Y + Height), true, true); ctx.LineTo(new Point(X + Width, Y + Height), true, true); ctx.LineTo(new Point(X + Width, Y), true, true); } internal static void DrawEllipseGeometry(this StreamGeometryContext ctx, double X, double Y, double Width, double Height) { X = X * 2; Y = Y * 2; Height = Height * 2; Width = Width * 2; ctx.BeginFigure(new Point(X, Y + Height / 2), true, true); ctx.ArcTo(new Point(X + Width, Y + Height / 2), new Size(Width / 2, Height / 2), 90, false, SweepDirection.Clockwise, true, true); ctx.ArcTo(new Point(X, Y + Height / 2), new Size(Width / 2, Height / 2), 90, false, SweepDirection.Clockwise, true, true); } public static Color GetRandomColor() { Random randomNum_1 = new Random(Guid.NewGuid().GetHashCode()); System.Threading.Thread.Sleep(randomNum_1.Next(1)); int int_Red = randomNum_1.Next(255); Random randomNum_2 = new Random((int)DateTime.Now.Ticks); int int_Green = randomNum_2.Next(255); Random randomNum_3 = new Random(Guid.NewGuid().GetHashCode()); int int_Blue = randomNum_3.Next(255); int_Blue = (int_Red + int_Green > 380) ? int_Red + int_Green - 380 : int_Blue; int_Blue = (int_Blue > 255) ? 255 : int_Blue; return GetDarkerColor(Color.FromArgb(Convert.ToByte(255),Convert.ToByte(int_Red), Convert.ToByte(int_Green), Convert.ToByte(int_Blue))); } //获取加深颜色 public static Color GetDarkerColor(Color color) { const int max = 255; int increase = new Random(Guid.NewGuid().GetHashCode()).Next(30, 255); //还可以根据需要调整此处的值 int r = Math.Abs(Math.Min(color.R - increase, max)); int g = Math.Abs(Math.Min(color.G - increase, max)); int b = Math.Abs(Math.Min(color.B - increase, max)); return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b)); } } }
下面欣赏一下我心血来潮时设计的:
下载地址:http://files.cnblogs.com/tong-tong/TTQRCodeFactory.zip
后记
自从本人淘宝女装店倒闭以后就一直不甘心,本来想开家店卖下二维码的设计赚点饭钱,结果事太多了,愣是没有时间来装修店铺...各位博友如果有二维码的设计需求的话也可以找我哦,价格公道,只收饭钱~~~~
出处:https://www.cnblogs.com/tong-tong/archive/2013/05/23/2758211.html
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/12957003.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2020-05-25 15:02 jack_Meng 阅读(6558) 评论(0) 编辑 收藏 举报