如何在ASP.NET和WPF中显示二维码

[原文发表地址] How to display a QR code in ASP.NET and WPF

[原文发表时间] 2014-01-19

        我曾半开玩笑的表示过根本没有一个很好的理由需要使用二维码,但是最近我在和Greg Shackles 一起制作一个小型启动的最小可行产品,并且我们有充分的理由要使用二维码。因为我们要在移动设备,网站以及应用程序间传送数据,而使用二维码真是一种较快捷的方法,也避免了蓝牙配对的混乱状况。

        如我所提到的,我们要在ASP.NET的网站上显示二维码,同时也在基于WPF框架实现的windows应用以及基于 Xamarin.框架,用C#实现的iphone 应用程序中也显示二维码。

     “ZXing"(斑马线)是一个很好的二维码代码库,对于JavaC#都有相应的接口 。C#/.NET,ZXing.NET是个相当棒的项目程序集,它将适用于多种平台的程序集放在了一起,这些平台包括了.NET 2.0到.NET 4.5、windows RT,Unity3D、 Portable libraries 等等。这个网站有许多例子,虽然我们没有找到一个和ASP.NET或WPF相关的,但是也没关系了,它们也只是生成和显示PNG 的图片。

        我从这里获得了ZXing.Net, 仅安装 ZXing.Net包就可以了。

如何在ASP.NET中展示二维码

        如果你用ASP.NET MVC生成一个二维码,你将会得到这段代码运行的页面,但是接着你需要决定是否需要利用 HTTP Handler 去生成图像,就像如下方式:

 <img src="/path/to/httphandlerthatmakesQRcodepng">

        或者你可以像我们一样用不同的方法,在HTML页面

        Greg 使用HTML助手输出整个图像标签,包括内嵌的图像,如:

 <img src="data:image/gif;base64,iVBORw0KG..." />

        我觉得图像以DataURI的方式显示在 HTML 页面中是很有趣的,但却经常被遗忘。如果你给一个一般的web开发者展示,他们会说"噢,是…我知道那些,但从未真正使用过它。"事实上,DATA URI已出现了很长一段时间。在dataurl.net你可以学到更多关于DataURI的内容。

        这是在ASP.NET MVC中使用HTML助手生成二维码的代码:      

 
          
public static class HtmlHelperExtensions
{
 public static IHtmlString GenerateRelayQrCode(this HtmlHelper html, string groupName, int height = 250, int width = 250, int margin = 0)
    {
        var qrValue = "whatever data you want to put in here";
        var barcodeWriter = new BarcodeWriter
        {
            Format = BarcodeFormat.QR_CODE,
            Options = new EncodingOptions
            {
                Height = height,
                Width = width,
                Margin = margin
            }
        };
 
        using (var bitmap = barcodeWriter.Write(qrValue))
        using (var stream = new MemoryStream())
        {
            bitmap.Save(stream, ImageFormat.Gif);
 
            var img = new TagBuilder("img");
            img.MergeAttribute("alt", "your alt tag");
            img.Attributes.Add("src", String.Format("data:image/gif;base64,{0}", 
                Convert.ToBase64String(stream.ToArray())));
 
            return MvcHtmlString.Create(img.ToString(TagRenderMode.SelfClosing));
        }
    }
}


          

        简洁又美观。在ZXing.NET内的BarcodeWriter类做了艰辛的工作: 我们不需要将二维码保存到磁盘,因为通过这个助手我们可以内嵌在html页面,而不需要一个单独的调用来获取图像。此外,我们决定将此页面缓存策略适用于内嵌图像,远胜于两次调用。

如何在WPF中展示二维码

注:这段代码可能是错的。我亲爱的读者,很高兴能听到来自你们的建议,因为我可能会漏掉什么或者没有一个清晰的方法可以将System.Drawing.Bitmap 的内容转换为System.Windows.Media.imaging.BitmapImage 。这种首先将图片信息保存到MemoryStream,然后转换为BitmapImage的做法,只是出于我的直觉,但是也需要对cacheoption属性进行设置。虽然它可以正常运行,但它可能不是正确的处理方式

        如果我找到了较为清晰的方式,我会更新代码的。

请参阅下面的更新:

        首先,ZXing.NET库里BarcodeWriter的正确使用方式如下:

 var qrcode = new QRCodeWriter();
var qrValue = "your magic here";
var barcodeWriter = new BarcodeWriter
 {
     Format = BarcodeFormat.QR_CODE,
     Options = new EncodingOptions
     {
         Height = 300,
         Width = 300,
         Margin = 1
     }
 };
 using (var bitmap = barcodeWriter.Write(qrValue))
 using (var stream = new MemoryStream())
 {
     bitmap.Save(stream, ImageFormat.Png);
     BitmapImage bi = new BitmapImage();
     bi.BeginInit();
     stream.Seek(0, SeekOrigin.Begin);
     bi.StreamSource = stream;
     bi.CacheOption = BitmapCacheOption.OnLoad;
     bi.EndInit();
     QRCode.Source = bi; //A WPF Image control
   }

        然后,将Bitmap写入内存流中进行操作,只不过,我们将二维码放到WPF图像控件的源属性中。                          

        Thomas Levesque建议可以使用System.Windows.Interop的扩展CreateBitmapSourceFromHBitmap(这解释了我为什么找不到System.Windows.Interop)。这种方法感觉也不是很好,因为它需要调用本地的Deleteobject方法,但无论如何,我想这个应该还是可以接受的。它就成了下面所展示的,并且运转正常!        

 using (var bitmap = barcodeWriter.Write(qrValue))
{
    var hbmp = bitmap.GetHbitmap();
    try
    {
       var source = Imaging.CreateBitmapSourceFromHBitmap(hbmp, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
       QRCode.Source = source;
    }
    finally
    {
        DeleteObject(hbmp);
    }
}