1. 程式人生 > >HTML5下Base64圖片處理結合攝像頭抓拍裁切

HTML5下Base64圖片處理結合攝像頭抓拍裁切

最近要實現一個現場報名功能,採用B/S結構系統實現現場報名,現場採集使用者資訊錄入系統。

前端使用bootstrap框架,後臺使用ASP.NET MVC4。

剛開始只需要使用者提供身份證,用讀卡器讀出身份證的資訊自動填充到輸入框中,然後補充其他資訊儲存即可。

身份證讀卡器就是這貨,USB介面。


做了個操作介面:


讀身份證資訊比較好辦,呼叫讀卡器介面對應的方法即可。

通過實驗發現介面方法讀取頭像照片時,得到的是Base64格式的jpg圖片,並且不包含“data:image/jpg;base64,”這段頭資訊,需要自己手工加上。圖片尺寸為102*126畫素,在圖片上右擊看屬性:


提交報名資訊時,後臺將獲取的Base64字串轉換成jpg並儲存在指定路徑下:


本來功能也就完成了,後來使用者提出沒帶身份證報名的情況,需要增加從檔案選擇照片和現場用攝像頭拍照兩種方式,先感慨一下需求變更,還是要想辦法實現功能。

分析後決定將檔案選取和攝像頭拍照用彈窗來操作,取得的圖片直接展示在頭像框處,並且為了和身份證讀卡器讀出的圖片格式相容,都設為Base64格式。這樣就形成了統一思路,不論用什麼方式獲得頭像照片(讀身份證、檔案選取、攝像頭拍照),均以Base64格式展示在操作介面,這樣提交到後臺處理時方式是一樣的。


================================= 分割一下 =================================

從檔案中選取照片的處理

瀏覽照片選中時,用js控制在操作介面中展示選中照片,同時父視窗頭像框處展示經過Base64處理過的影象。點選右上角關閉按鈕或右下角確定按鈕時,關閉當前彈窗。


元素"imgFile"為圖片選擇視窗中要展示的圖片,"imgAvatar"為父視窗中的頭像框,"hPhoto"為父視窗記錄Base64內容的隱藏域,注意去掉了"data:image/jpeg;base64,"這段頭資訊,只保留圖片資料內容。

此時頭像框中圖片格式與讀身份證得到的圖片格式一樣,後臺儲存方法都不用改。即使選擇的圖片格式不是jpg的,仍然會在後臺程式碼中自動轉換成jpg格式。

=================================再分割一下=================================

攝像頭拍照的處理稍微麻煩一下,主要在於拍照的圖片是橫版的,但系統要求的頭像圖片是豎版的,需要進行裁切。

攝像頭就是普通那種USB介面的攝像頭,免驅動的。


網頁呼叫攝像頭拍照有多種方案,對比後採用的是flash方式。

專案中引用需要的資原始檔:


頁面中呼叫:

    <script src="/assets/js/jquery-1.8.3.min.js" type="text/javascript"></script>
    <script src="/assets/js/webcam/jquery.webcam.js"></script>

思路是這樣的:flash顯示攝像頭實時畫面,點選“拍照”按鈕時捕獲當前畫面,然後按比例裁切中間一部分影象展示在畫布中。

攝像頭實時畫面設定為320*240畫素,按照頭像實際尺寸計算,應該擷取拍照畫面中間的194*240區域。

為了方便操作者預覽,在攝像頭實時畫面的左右兩側增加了一個半透明區域,意思是這兩塊區域要刪掉,只保留中間一部分。

彈窗中左側是攝像頭畫面,下方有“拍照”按鈕,拍照的圖片自動裁切後顯示在右側,父視窗同步顯示拍照結果。

左右兩側的半透明區域是用css控制的div透明度,注意flash呼叫攝像頭的z-index數值,要將半透明區域疊加到flash之上才行。

攝像頭畫面只保留中間的194*240區域的內容,因此拍照後要將原始圖片從(63,0)位置開始裁切大小為194*240區域的影象,js程式碼是image = ctx.getImageData(63, 0, 194, 240);


顯示攝像頭畫面和抓拍畫面的html:


其中,id為“webcam”的div在頁面載入時會append上flash,由flash呼叫攝像頭。

=================================待改進地方 =================================

1、程式中bootstrap框架採用ACE1.3.3版本,開啟對話視窗時,是將彈窗檔案解析後附加在本頁中,因此會受本月的指令碼和程式碼影響。從檔案選取圖片功能用預設的對話視窗可以實現功能,但攝像頭拍照功能則不能生效,我只能用模態視窗來實現效果,並且在點選“拍照”按鈕時將抓拍的圖片回傳給父視窗。

2、因客戶只使用IE瀏覽器,並且版本也固定,因此可以不用考慮過多相容問題。身份證讀卡器使用Activex控制元件註冊,如果是火狐或谷歌瀏覽器要載入不同的控制元件。另外實時攝像頭畫面兩側半透明區域只在IE下起作用,其他瀏覽器要再處理。

=================================總結=================================

1、通過三種不同方式獲取頭像資訊,傳到後臺儲存時已經處理成同樣的格式,這也是程式碼分離原則的體現。以頭像框為中轉站,前臺js各種處理,達到同樣格式的Base64圖片;後臺獲取圖片字串,統一儲存成jpg格式。也相當於呼叫後臺的一個方法時,通過各種手段將傳入引數統一好格式,伺服器端方法只需要接收到引數內容處理即可,不需要再做更多情況判斷。

2、不同版本的bootstrap有一定的瀏覽器相容問題,特別是jquery版本。某些時候使用原生js是更好的選擇。

3、花哨的功能儘量少,用最簡單的方式實現功能,穩定性是最好的。

附:程式碼檔案

父頁面部分程式碼

<input type="hidden" id="hPhoto" name="hPhoto" />
<input type="file" id="picFile" name="picFile" onchange="selectPicFile()" style="display:none;" />

<img id="imgAvatar" alt="" src="/assets/avatars/default.jpg" width="102" height="126" />

<div class="col-sm-4 align-left">

<a href="#" role="button"  onclick="CapturePicture()"><i class="fa fa-camera fa-1x" title="從攝像頭拍照"> 拍照</i></a>

<br />

<a href="FilePicture" role="button" data-toggle="modal" data-target="#FilePicture"><i class="fa fa-folder-open fa-1x" title="從檔案中選擇"> 檔案</i></a>

</div>

<div id="FilePicture" class="modal fade" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>

<script type="text/javascript">

jQuery(function ($) {

$("#FilePicture").on("hidden.bs.modal", function () {
                $(this).removeData("bs.modal");
});

        function CapturePicture() {
            return window.showModalDialog("CapturePicture", GetResult, "dialogWidth=620px,dialogHeight=400px");
        }
        function GetResult(imageContent) {
            document.getElementById('imgAvatar').src = imageContent;
            document.getElementById('hPhoto').value = imageContent.substring(imageContent.indexOf(";base64,") + 8);
        }

});

</script>

檔案選擇子頁面(FilePicture)

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta charset="utf-8" />
        <title></title>
        <script type="text/javascript">
            function showImage(file) {
                var imageContent = '';
                if (!file.files || !file.files[0]) {
                    return;
                }
                var reader = new FileReader();
                reader.onload = function (evt) {
                    imageContent = evt.target.result;
                    document.getElementById('imgFile').src = imageContent;
                    document.getElementById('imgAvatar').src = imageContent;
                    document.getElementById('hPhoto').value = imageContent.substring(imageContent.indexOf(";base64,") + 8);
                }
                reader.readAsDataURL(file.files[0]);
            }
        </script>


    </head>
    <body class="no-skin">
        <div class="modal-header">
       <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
       <h3 class="smaller lighter blue no-margin">選擇照片</h3><h5>(尺寸:102*126畫素或等比例)</h5>
        </div>
        <div class="modal-body">
            <table width="100%" border="0" cellpadding="0" cellspacing="0">
                <tr>
                    <td align="left">
                        <input type="file" id="picFile" name="picFile" onchange="showImage(this)" />
                    </td>
                </tr>
                <tr>
                    <td>&nbsp;</td>
                </tr>
                <tr>
                    <td>
                        <img id="imgFile" style="height:220px;" alt="" />
                    </td>
                </tr>
            </table>
        </div>
        <div class="modal-footer">
            <button type="button" data-dismiss="modal" data-bb-handler="success" class="btn btn-sm btn-success">
                <i class="ace-icon fa fa-check"></i> 確定
            </button>
        </div>
    </body>
</html>

攝像頭抓拍子頁面(CapturePicture)

@{
    Layout = null;
}
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>拍照</title>
    <style type="text/css">
    #webcam {
        width: 320px;
        }
    #webcam {
        position:relative;
        }
    object {
        display:block; /* HTML5 fix */
        position:relative;
        z-index:100;
        }        
    .div1{
        width:320px;
        height:240px;
        position:relative;
        border:1px solid #cccccc;
   }
    .div2{
   width:63px;
   height:240px;
   position:absolute;
   left:0;
   top:0;
   background:#000000;
   z-index:9999;
   opacity:0.3;
   filter:alpha(opacity:30);
   moz-opacity:0.3;
   }
    .div3{
   width:63px;
   height:240px;
   position:absolute;
   right:0;
   top:0;
   background:#000000;
   z-index:9999;
   opacity:0.3;
   filter:alpha(opacity:30);
   moz-opacity:0.3;
   }
    </style>
    <script src="/assets/js/jquery-1.8.3.min.js" type="text/javascript"></script>
    <script src="/assets/js/webcam/jquery.webcam.js"></script>
    <script type="text/javascript">
        var pos = 0;
        var ctx = null;
        var cam = null;
        var saveCB;
        var image = [];


        $(document).ready(function () {
            var canvas = document.getElementById("canvas");
            if (canvas.getContext) {
                ctx = document.getElementById("canvas").getContext("2d");
                ctx.clearRect(0, 0, 320, 240);
                var img = new Image();
                img.src = "";
                img.onload = function () {
                    ctx.drawImage(img, 0, 0);
                }
                image = ctx.getImageData(0, 0, 320, 240);
            }


            if (canvas.toDataURL) {
                ctx = canvas.getContext("2d");
                image = ctx.getImageData(63, 0, 194, 240);
                saveCB = function (data) {
                    var col = data.split(";");
                    var img = image;
                    for (var i = 63; i < 257; i++) {
                        var tmp = parseInt(col[i]);
                        img.data[pos + 0] = (tmp >> 16) & 0xff;
                        img.data[pos + 1] = (tmp >> 8) & 0xff;
                        img.data[pos + 2] = tmp & 0xff;
                        img.data[pos + 3] = 0xff;
                        pos += 4;
                    }
                    if (pos >= 4 * 194 * 240) {
                        ctx.putImageData(img, 0, 0);
                        pos = 0;
                    }
                };


            } else {
                saveCB = function (data) {
                    image.push(data);
                    pos += 4 * 194;
                    if (pos >= 4 * 194 * 240) {
                        pos = 0;
                    }
                };
            }


            jQuery("#webcam").webcam({


                mode: "callback",
                swffile: "/assets/js/webcam/jscam_canvas_only.swf",
                onCapture: function () {
                    webcam.save();
                    var canvas = document.getElementById("canvas")
                    var imageContent = canvas.toDataURL("image/png")
                    var callBack = window.dialogArguments;
                    if (callBack != undefined && callBack != null) {
                        callBack(imageContent);
                    }
                },
                onSave: saveCB,
                debug: function (type, string) {
                    jQuery("#status").html(type + ": " + string);
                },
                onLoad: function () {
                    var cams = webcam.getCameraList();
                    for (var i in cams) {
                        jQuery("#cams").append("<li>" + cams[i] + "</li>");
                    }
                }
            });
        });


</script>
</head>


<body class="no-skin" style="margin:10px;">
    <table width="100%" border="0" cellpadding="0" cellspacing="0">
        <tr>
            <td height="56"><ul id="cams"></ul></td>
            <td width="50">&nbsp;</td>
            <td><p id="status"></p></td>
        </tr>
        <tr style="height:3px;">
            <td><hr /></td>
            <td></td>
            <td><hr /></td>
        </tr>
        <tr>
            <td colspan="3">&nbsp;</td>
        </tr>
        <tr>
            <td align="center">
                攝像頭畫面
            </td>
            <td></td>
            <td align="center">
                拍照結果
            </td>
        </tr>
        <tr>
            <td align="center">            
                <div id="webcam"  class="div1">
                    <div class="div2"></div>
                    <div class="div3"></div>
                </div>
            </td>
            <td></td>
            <td align="center">
                <div>
                    <canvas id="canvas" width="194" height="240"></canvas>
                </div>
            </td>
        </tr>
        <tr>
            <td align="center"><a href="javascript:webcam.capture();void(0);">拍照</a></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td colspan="3" height="20">&nbsp;</td>
        </tr>
        <tr>
            <td colspan="3" height="50" align="center" style="background-color:#cccccc"><input type="button" value="完成" onclick="window.close();" /></td>
        </tr>
    </table>


</body>
</html>

相關推薦

HTML5Base64圖片處理結合攝像頭抓拍

最近要實現一個現場報名功能,採用B/S結構系統實現現場報名,現場採集使用者資訊錄入系統。 前端使用bootstrap框架,後臺使用ASP.NET MVC4。 剛開始只需要使用者提供身份證,用讀卡器讀出身份證的資訊自動填充到輸入框中,然後補充其他資訊儲存即可。 身份證讀卡器就

Android圖片上傳(頭像+原圖原樣)

還是那句話,最近專案比較忙拖了很久這篇文章終於完成了! 先看一下效果圖: (一)頭像裁切、上傳伺服器(效果圖) 一般都是有圓形顯示頭像的,這裡我自定義了一個ImageView,頁面很乾淨但是看著很上檔次吧! 點選頭像從底部彈出一個對話方塊,提示使用者頭像來自相機或者相簿,這

圖片處理Base64

col ack 頁面 發送 http 簡單 文件大小 pan class   網頁上的圖片資源如果采用 http 形式的 url 的話都會額外發送一次請求,網頁發送的 http 請求次數越多,會造成頁面加載速度越慢。而采用Base64格式的編碼,將圖片轉化為字符串後,圖

base64圖片上傳處理方式

adb 信息 als 上傳圖片 上傳 文件 chang exist match 前臺傳圖片的base64格式,後臺處理方式//處理圖片信息 返回對應的路徑public function uploadBaseIma($imgArr){ $result = array()

前端性能優化------------圖片處理Css Sprites&Base64

大於 字符 ebp 錯誤 過程 inf 嵌入 定位 性能 Css Sprites Css Sprites我們叫做雪碧圖或者css精靈,其原理就是將許多小的圖片合到一張大的圖片中,然後使用background-image引用圖片,使用background-position來定

還在羨慕微信/微博的圖片處理?-android酷炫圖片處理()

微信一向是android開發者們模仿的物件,上篇文章中,我介紹了一個和微信圖片壓縮,壓縮效果差不多的庫Luban,這篇文章還會介紹高仿微信從檔案系統選擇圖片。此外微博載入超長大圖功能也很酷炫(其實微信朋友圈也有),這篇文章也給出了實現這種效果的功能庫,當然,除此之外還有很多其他酷炫效果的

圖片檔案轉化為位元組陣列字串,並對其進行Base64編碼處理和 對位元組陣列字串進行Base64解碼並生成圖片

public static String imageToBase64(String path) { // 將圖片檔案轉化為位元組陣列字串,並對其進行Base64編碼處理 byte[] data = null; // 讀取圖片位元組

(python)subprocess利用ffmpeg處理多目錄圖片合成某一幀率的視訊

import os import subprocess path="/home/jinbeibei/File/video_prediction2018/iclr2017mcnet-master/data/DAVIS/Annotations/480p" for f

關於實現接收base64圖片資料並以圖片儲存到本地的處理

public function saveBase64File($img,$name=''){ $base_img = str_replace('data:image/jpeg;base64,','', $img); // 設定檔案路

基於HTML5 Canvase的線上畫圖及圖片處理工具

簡介       這是基於HTML5的Canvas而實現的線上畫圖及簡單圖片處理的工具,是我的計算機圖形學期末課程設計作業。主要功能包括:畫圖、顏色反轉、轉灰度圖、陰影效果、橫向漸變、縱向漸變等。處理

結合springmvc,使用ajax上傳base64圖片資料

一、前端: <input type="file" id="myImage" name="myImage"/> <script type="text/javascript"> $("#myImage").bind("ch

前端開發之使用base64模式處理圖片

最近在做訊息推送,涉及到圖片處理這一塊,於是就使用base64的方式處理圖片.做一個簡單的總結.算是備忘.如果能幫到大家最好. 一.什麼是base64       Base64就是一種基於64個可列印字元來表示二進位制資料的方法。  (百度百科)    二.如何使用    

base64圖片在各種瀏覽器的相容性處理

IE瀏覽器目前最高的版本是v11,而微軟放棄了IE,轉向新的瀏覽器開發,並取名為Edge。base64圖片在IE9及以後的圖片均能顯示沒有問題,而Firefox, Chrome, Safari等非IE瀏覽器都能正常顯示,所以顯得IE瀏覽器比較low。那麼相容性究竟應該怎麼來處理呢? 分三種情況。 (1)IE

如何使用 HTML5 的picture元素處理響應式圖片

圖片在響應式網頁設計中是出了名的最具挑戰性的方面之一。今天我們就來看看如何使用 <picture> 元素來處理響應式圖片. 讓我們先了解一下問題 固定寬度,畫素完美的網站設計已經離我們遠去了。在寬屏顯示器,網際網路電視,多尺寸的平板電腦和智慧手機的今天,我們的設計必須應付一切可能,將寬由 32

html5 canvas 載入圖片URL並轉換成base64

非同步載入圖片到canvas並拿掉data:image;base64部分。 function convertImgToBase64(url, callback, outputFormat){

Linux使用v4l2程式設計操作攝像頭裝置獲取圖片

進行操作前請參考我的另一篇部落格: 看懂之後再研究下面的程式: /***************************************************** * 檔名:GetYuyv.c * 檔案描述:linux下使用v4l2程式設計操作

通過圖片地址,將圖片處理base64,使用ajax上傳圖片

需求 群裡的一個小朋友一直要求我幫他實現以下,我就寫了一個案例。需求就是,他用canvas生成了一個base64格式的圖片,然後需要將這個圖片上傳到伺服器上面去。 程式碼 <!doctype html> <html lang="en"

base64加密圖片處理

兩種 例子 鏈接 replace html htm 加密 with open 加密圖片 場景:下載html中內嵌的base64加密圖片 舉個例子,博客園的插入圖片有兩種方式,一是引用圖片鏈接,二是直接粘貼2進制圖片文件。以第二種方式的圖片則是以base64加密的方式內嵌在

css3圖片處理方式 object-fit

含義 class 替換 down 區域 尺寸 屬性 obj over .fill { object-fit: fill; } .contain { object-fit: contain; } .cover { object-fit: cover; } .none { o

Android 中圖能夠用到的圖片處理類 BitmapUtils

andro radius title can rup decode eww row 上下 Android在實際開發中非常多時候都要對圖片進行一定的處理,這裏總結的BitmapUtils 類包含一下幾個功能: 1.Android圖片倒影, 2.Android圖片模糊處理,