現在網上很多應用都是用二維碼來分享網址或者其它的信息。尤其在移動領域,二維碼更是有很大的應用場景。
因為項目的需要,需要在網站中增加一個生成二維碼分析網址的功能,在谷歌大幅度抽筋的情況下無奈使用百度。百度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