web 中使用 谷歌 zxing.dll 识别二维码实例

好久没上来看看了,工作有点点忙。

最近有个项目,在手机端实现调用摄像头拍照识别二维码信息。


在网上找了一些资料,放在这里,备忘。

方案一:

用 HTML5 调用摄像头,获取画面然后通过 canvas 拿到图片,在用 zxing 组件识别。

<script type="text/javascript">
        var sel, fr;
        $(function () {
            $('#canvas').hide();
            try {
                sel = document.getElementById('fileselect'); // get reference to file select input element

                window.addEventListener("DOMContentLoaded", function () {
                    // Grab elements, create settings, etc.
                    var canvas = document.getElementById("canvas"),
                    context = canvas.getContext("2d"),
                    video = document.getElementById("video"),
                    videoObj = { "video": true },
                    errBack = function (error) {
                        if (error.PERMISSION_DENIED) {
                            AlertDialog.Alert("", "用户拒绝了浏览器请求媒体的权限", "");
                            //AlertDialog.Alert('用户拒绝了浏览器请求媒体的权限', '提示');
                        } else if (error.NOT_SUPPORTED_ERROR) {
                            AlertDialog.Alert("", "对不起,您的浏览器不支持拍照功能,请使用其他浏览器", "");
                            //AlertDialog.Alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器', '提示');
                        } else if (error.MANDATORY_UNSATISFIED_ERROR) {
                            //AlertDialog.Alert('指定的媒体类型未接收到媒体流', '提示');
                            AlertDialog.Alert("", "指定的媒体类型未接收到媒体流", "");
                        } else {
                            AlertDialog.Alert("",'系统未能获取到摄像头,请确保摄像头已正确安装。或尝试刷新页面,重试', "");
                        }
                    };


                    var message = "为了获得更准确的测试结果,请尽量将面部置于红框中,然后进行拍摄、扫描。 点击“OK”后,请在屏幕上方出现的提示框选择“允许”,以开启摄像功能";
                    // Put video listeners into place
                    if (navigator.getUserMedia) { // Standard
                        if (navigator.userAgent.indexOf('MQQBrowser') > -1) {
                            AlertDialog.Alert("",'对不起,您的浏览器不支持拍照功能,请使用其他浏览器', "");
                            return false;
                        }
                        AlertDialog.AlertAndOkfn("", message, "", false, "", function () {
                            $(document).scrollTop($(window).height());
                        });
                        //AlertDialog.Alert(message, '提示', function () {
                        //    $(document).scrollTop($(window).height());
                        //});

                        navigator.getUserMedia(videoObj, function (stream) {
                            video.src = stream;
                            video.play();
                            alert(11);
                            $('#lifescan #main .btn_click').css('margin-top', '-550px');
                            video.addEventListener('loadeddata', function () {
                                $(document).scrollTop($(window).height());
                            }, false);
                            $('#snap').click(function () {
                                //$('.scan-area').show();
                                $('#cream_loading').toggle();
                                context.drawImage(video, 0, 0, 640, 480);
                                convertCanvasToImage();
                            });
                        }, errBack);
                    } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
                        AlertDialog.AlertAndOkfn("", message, "", false, "", function () {
                            $(document).scrollTop($(window).height());
                        });

                        //AlertDialog.Alert(message, '提示', function () {
                        //    $(document).scrollTop($(window).height());
                        //});

                        navigator.webkitGetUserMedia(videoObj, function (stream) {
                            video.src = window.webkitURL.createObjectURL(stream);
                            video.play();
                            $('#lifescan #main .btn_click').css('margin-top', '-550px');
                            video.addEventListener('loadeddata', function () {
                                $(document).scrollTop($(window).height());
                            }, false);
                            if (navigator.userAgent.indexOf('UCBrowser') > -1) {
                                $('#lifescan #main .btn_click').css('margin-top', '-10px');
                            }
                            $('#snap').click(function () {
                                $('#cream_loading').toggle();
                                context.drawImage(video, 0, 0, 640, 480);
                                convertCanvasToImage();
                            });
                        }, errBack);

                    }
                    else if (navigator.mozGetUserMedia) { // Firefox-prefixed
                        AlertDialog.AlertAndOkfn("", message, "", false, "", function () {
                            $(document).scrollTop($(window).height());
                        });

                        //AlertDialog.Alert(message, '提示', function () {
                        //    $(document).scrollTop($(window).height());
                        //});


                        navigator.mozGetUserMedia(videoObj, function (stream) {
                            video.src = window.URL.createObjectURL(stream);
                            video.play();
                            video.addEventListener('loadeddata', function () {
                                $(document).scrollTop($(window).height());
                            }, false);
                            $('#lifescan #main .btn_click').css('margin-top', '-550px');

                            $('#snap').click(function () {
                                $('#cream_loading').toggle();
                                context.drawImage(video, 0, 0, 640, 480);
                                convertCanvasToImage();
                            });
                        }, errBack);

                    }
                    else if (navigator.msGetUserMedia) {
                        AlertDialog.AlertAndOkfn("", message, "", false, "", function () {
                            $(document).scrollTop($(window).height());
                        });

                        //AlertDialog.Alert(message, '提示', function () {
                        //    $(document).scrollTop($(window).height());
                        //});

                        navigator.msGetUserMedia(videoObj, function (stream) {
                            $(document).scrollTop($(window).height());
                            video.src = window.URL.createObjectURL(stream);
                            video.play();
                            $('#lifescan #main .btn_click').css('margin-top', '-550px');
                            video.addEventListener('loadeddata', function () {
                                $(document).scrollTop($(window).height());
                            }, false);
                            $('#snap').click(function () {
                                $('#cream_loading').toggle();
                                context.drawImage(video, 0, 0, 640, 480);
                                convertCanvasToImage();
                            });
                        }, errBack);

                    }
                    else {
                        var userAgent = navigator.userAgent;
                        if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Oupeng") == -1 && userAgent.indexOf("360 Aphone") == -1) {
                            sel.addEventListener('change', function (e) {
                                var f = sel.files[0]; // get selected file (camera capture)
                                fr = new FileReader();
                                fr.onload = receivedData; // add onload event

                                fr.readAsDataURL(f); // get captured image as data URI
                            });
                            $('#imgtag').show();
                            $('.div_video').hide();
                            $('#snap').click(function () {
                                sel.click();
                            });
                        } //判断是否Safari浏览器
                        else {
                            AlertDialog.Alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器', '提示');
                        }
                    }
                }, false);
            }
            catch (err) {
                AlertDialog.Alert("", "对不起,您的浏览器不支持拍照功能,请使用其他浏览器", "");

                //AlertDialog.Alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器', '提示');
            }
        });
        // for iOS
        // create file reader
        function receivedData() {
            // readAsDataURL is finished - add URI to IMG tag src
            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            var imgtag = document.getElementById('imgtag'); // get reference to img tag
            imgtag.src = fr.result;
            $('#cream_loading').toggle();

            try {
                setTimeout(function () {
                    context.drawImage(imgtag, 0, 0, 640, 480);
                    convertCanvasToImage();
                }, 500);

            }
            catch (err) {
                alert(err);
            }
        }
        //帆布转换成图像并保存图片
        function convertCanvasToImage(canvas) {
            var image = new Image();
            image.src = document.getElementById("canvas").toDataURL("image/png");
            //alert(image.src);
            //删除字符串前的提示信息“data:image/png;base64”
            var b64 = image.src.substring(22);
            var myDate = new Date();
            var filename = myDate.getTime();
            $.post("/Article/SavePhoto", { data: b64, name: filename }, function (result) {
                if (result.success) {
                    $('#cream_loading').toggle();
                    window.location.href = "/yourreenex?photo=" + result.photo;
                }
            });
            return image;
        }

    </script>

<div id="main" class="masthead">
        <div id="face_scan_camera" class="container blackbg" style="height: 792px;">
            <div style="width: 1400px; margin: 0 auto;">
                <video id="video" width="1400" height="790" autoplay="autoplay" style="margin: 0 auto; position: relative; z-index: 100;"></video>

            </div>
            <div class="camera-mask"></div>
            <div class="camera-area" style="width: 450px; height: 350px; background: url(/images/lifescan/scan_kuang1.png) no-repeat; z-index: 102; top: 560px; left: 780px;">
                <img src="/images/lifescan/scan_kuang1.png" />
                <div class="scan-area" style="height: 585px; width: 580px; display: none;">
                    <canvas id="canvas" width="1054" height="790" style="display: inline-block; margin: 0 auto; position: relative; left: 13px; top: 70px; z-index: 100;"></canvas>

                </div>
                <a id="snap">
                    <img src="/images/lifescan/camera_btn.png" /></a>

            </div>

        </div>
        <div id="cream_loading" style="display: none; position: absolute; margin: -62px 0 0 -62px; top: 50%; left: 50%; height: 124px; width: 124px; z-index: 2001;">
            <img src="/Images/cream_loading.gif" />
        </div>

    </div>


这个方案里面调用摄像头比较复杂,在做的过程中发现一个投机取巧的办法。

方案二:

直接在页面上面放一个上传控件,在手机端的某些浏览器中(如 qq 浏览器,谷歌,android 自带的等)也能打开摄像头!luck!

于是开搞!

<script type="text/javascript" src="scripts/jquery-1.11.1.min.js"></script>
    <script type="text/javascript">
        var imgWidth = 0;
        $(function () {
            imgWidth = $("#divMain").width();
        })

        function setImagePreview() {
            var preview, img_txt, localImag, file_head = document.getElementById("<%=fuRQCodeFile.ClientID%>"), picture = file_head.value;
            //var preview, img_txt, localImag, file_head = document.getElementById("file_head"), picture = file_head.value;
            if (!picture.match(/.jpg|.gif|.png|.bmp/i))
                return alert("您上传的图片格式不正确,请重新选择!"), !1;

            if (preview = document.getElementById("preview"), file_head.files && file_head.files[0]) preview.style.display = "block",
                preview.style.width = imgWidth + "px",
				preview.src = window.navigator.userAgent.indexOf("Chrome") >= 1 || window.navigator.userAgent.indexOf("Safari") >= 1 ? window.webkitURL.createObjectURL(file_head.files[0]) : window.URL.createObjectURL(file_head.files[0]);
            $("#<%=btnUpload.ClientID%>").click();
            //else {
            //    file_head.select(),
            //	file_head.blur(),
            //	img_txt = document.selection.createRange().text,
            //	localImag = document.getElementById("localImag"),
            //    //localImag.style.width = "63px",
            //    //localImag.style.height = "63px";
            //    localImag.style.width = imgWidth + "px";

            //    try {
            //        localImag.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)",
            //		localImag.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = img_txt
            //    } catch (f) {
            //        return alert("您上传的图片格式不正确,请重新选择!"),
            //		!1
            //    }
            //    preview.style.display = "none",
            //	document.selection.empty();
            //}
            //return document.getElementById("DivUp").style.display = "block",
            //!0
        }

    </script>

<div>
            <div>
                <asp:Label ID="LblContent" runat="server"></asp:Label>
                <div>
                    <asp:FileUpload ID="fuRQCodeFile" οnchange="javascript:setImagePreview();" runat="server" />
                    <%--<input type="file" name="file_head" id="file_head" οnchange="javascript:setImagePreview();" />--%>
                </div>
            </div>
            <div id="localImag">
                <img id="preview" width="-1" height="-1" style="display: none" />
            </div>
            <div style="display: none;">
                <asp:Button ID="btnUpload" Text="识别二维码" OnClick="btnUpload_Click" runat="server" Style="display: none;" />
            </div>
        </div>

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using ZXing;

namespace QR_Code
{
    public partial class QRCodeTest : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 将大图转换成小图(图片太大会导致解析异常)
        /// </summary>
        /// <param name="bm"></param>
        protected void ConverToSmallImg(ref Bitmap bm)
        {
            Bitmap bitmap = (Bitmap)Bitmap.FromStream(fuRQCodeFile.FileContent, false);
            System.Drawing.Image img = System.Drawing.Image.FromStream(fuRQCodeFile.FileContent);

            int sHeight, sWidth = 200;
            int temp = img.Width / sWidth;
            sHeight = img.Height / temp;

            bm = new Bitmap(sWidth, sHeight);
            Graphics gph = Graphics.FromImage(bm);
            gph.DrawImage(img, 0, 0, sWidth, sHeight);
        }

        protected void btnUpload_Click(object sender, EventArgs e)
        {
            try
            {
                Bitmap bitMap = null;
                ConverToSmallImg(ref bitMap);

                BarcodeReader reader = new BarcodeReader();
                Result result = reader.Decode(bitMap);

                LblContent.Text = result.Text;
            }
            catch (Exception ex)
            {
                LblContent.Text = "出现异常" + ex.Message;
            }
        }

    }
}

这样就能打开摄像头,拍一张相片,然后放到 fileupload 上面,通过 jquery 模拟点击上传,然后后台通过 zxing 识别。

需要注意的是,现在 android 手机拍出来的相片非常大!会出现异常,所以把图片等比缩放,将大大提升识别成功率。


附:

zxing GitHub下载地址:https://github.com/zxing/zxing

选择 C# 版本的下载就行


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值