10 فروردین 1399
برای اسکن تصاویر، ابزارهای مختلفی وجود دارند. چنانچه برنامه شما تحت وب باشد، باید بتوانید بدون هیچ نرمافزار واسطی از اسناد خود اسکن گرفته و آن را در پرونده و با نام مورد نظرتان ذخیره کنید. باتوجه به اینکه وبکم USB توسط مرورگرها شناخته میشوند، در این پروژه قصد داریم با کمک یک وبکم به اسکن اسناد خود بپردازیم و در مرحله بعد با خواندن qrcode - توسط وبکم - که میتواند شماره یونیک ما باشد، تصویر را ذخیره کنیم
1) اسکن تصویر توسط وبکم
2) اسکن تصویر و qrcode توسط وبکم
با چند خط کد جاوااسکریپت و در بستر Html5 میتوان از وبکم لپ تاپ یا وبکم متصل به رایانه استفاده کرد. اما ما در این مثال از یک کتابخانه آماده با نام webcamjs استفاده میکنیم که کار را برای ما راحتتر میکند. یادآوری میکنم تمام فایلهای لازم در سمپل این مقاله وجود دارد. حال مثال ساده زیر را بررسی میکنیم:
<html> <head> <meta charset="utf-8" /> <title>Webcam</title> <script src="webcam.min.js"></script> </head> <body> <div id="div_camera"></div> <script> Webcam.set({width: 640,height: 480}); Webcam.attach('#div_camera'); </script> </body> </html>
همان طور که مشاهده میکنید ابتدا کتابخانه webcam.min.js را به پروژه خود افزوده و یک div هم جهت نمایش تصویر وبکم ایجاد کردهایم. سپس با نوشتن دو دستور ساده Webcam.set و Webcam.attach ابتدا ابعاد تصویر وبکم را تعیین کرده و بعد آن به المان div پیوست میکنیم. کار تمام است.
گام بعدی که در مثال زیر آوردهام این است که میخواهیم:
الف) از تصویر زنده وبکم عکس بگیریم
ب) محدوده و ابعاد عکس را مشخص کنیم
ج) عکس نهایی را در سرور ذخیره نماییم
<html> <head> <meta charset="utf-8" /> <title>Webcam</title> <script src="webcam.min.js"></script> <script src="croppr.js"></script> <script src="jquery.min.js"></script> <link href="croppr.css" rel="stylesheet" /> </head> <body style="text-align:center"> <h1 style="direction:rtl">اسکن توسط وب کم</h1> <button onClick="start_scan()" id="btn_1">شروع</button> <button onClick="webcam_stop()" id="btn_3" hidden>عکس</button> <button onClick="save_image()" id="btn_2" hidden>ذخیره</button> <span id="div_camera"></span> <div id="div_img"></div> <script> var snapshot; function start_scan() { $('#div_img').hide(); $('#div_camera').show(); $('#btn_1').hide(); $('#btn_2').hide(); $('#btn_3').show(); Webcam.set({width: 640,height: 480}); Webcam.attach('#div_camera'); } function webcam_stop() { Webcam.snap( function(data_uri) { snapshot = data_uri; $('#div_img').show(); $('#div_camera').hide(); $('#div_img').html('<img id="cropper" src="" />'); $('#cropper').prop('src',data_uri); }); Webcam.reset(); $('#btn_1').show(); $('#btn_3').hide(); $('#btn_2').show(); start_crop(); } function start_crop() { croppr = new Croppr('#cropper', { aspectRatio: 1, minSize: [100, 100, 'px'] }); } function save_image() { x = y = w = h = 0; var value = croppr.getValue(); x = value.x; y = value.y; w = value.width; h = value.height; $.ajax({ type: "POST", url: "index_save.php", data: { imgBase64: snapshot, x: x, y: y, w: w, h: h }, success: function(res) { $('#div_img').html('<img id="cropper" src="'+res+'" />'); $('#btn_2').hide(); } }); } </script> </body> </html>
<?php header('Content-Type: text/html; charset=utf-8'); $fileData = explode(',', $_POST['imgBase64']); $file = base64_decode($fileData[1]); $src = imagecreatefromstring($file); $src_x = $_POST['x']; $src_y = $_POST['y']; $src_width = $_POST['w']; $src_height = $_POST['h']; $thumb_width = 300; $thumb_height = 300; $thumb_x = 0; $thumb_y = 0; $thumb = imagecreatetruecolor($thumb_width,$thumb_height); $thumb_title = time().".jpg"; imagecopyresampled($thumb, $src, $thumb_x, $thumb_y, $src_x, $src_y, $thumb_width, $thumb_height, $src_width, $src_height); imagejpeg($thumb, $thumb_title, 80); echo $thumb_title; ?>
ابتدا علاوه بر کتابخانه قبلی دو کتابخانه جیکوئری و Croppr را به پروژه خود اضافه میکنیم. کار Croppr این است که به ما امکان تعیین دلخواه محدوده عکس را میدهد تا بتوانیم عکس را برش دهیم.
الف) جهت عکس گرفتن از تصویر وبکم طبق مثال فوق از دستور Webcam.snap استفاده میکنیم؛ مقدار برگشتی این تابع محتوای عکس ماست که میتوانیم آن را در نشانی src عکس قرار دهیم.
ب) به کمک Croppr محدوده تصویر را جهت ذخیره کردن مشخص میکنیم. تابع start_crop یک Croppr جدید فراخوانی میکند که در این مثال نسبت تصویر را 1:1 تعیین کردهایم. سپس با دستور croppr.getValue مختصات و ابعاد تصویر برش خورده را به دست میآوریم. در نهایت متغیرهای مختصات و تصویر را توسط آجاکس به سمت سرور ارسال میکنیم.
ج) در سمت سرور مانند فایل index_save.php متغیرها را دریافت کرده و تصویر را با نام دلخواه ذخیره میکنیم.
جهت اسکن و تشخیص مقدار qrcode نیز می توان از کتابخانه هایی نظیر jsQR استفاده کرد. در مثال ساده زیر پس از فراخوانی کتابخانه jsQR به محض این که وب کم کیوآرکد را تشخیص دهد، مقدار آن نمایش داده می شود.
<html> <head> <meta charset="utf-8" /> <title>Qrcode</title> <script src="jsQR.js"></script> </head> <body> <canvas id="canvas" hidden></canvas> <div id="message">وب کم فعال نیست</div> <script> var video = document.createElement("video"); var canvasElement = document.getElementById("canvas"); var canvas = canvasElement.getContext("2d"); var message = document.getElementById("message"); function drawLine(begin, end, color) { canvas.beginPath(); canvas.moveTo(begin.x, begin.y); canvas.lineTo(end.x, end.y); canvas.lineWidth = 4; canvas.strokeStyle = color; canvas.stroke(); } navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) { video.srcObject = stream; video.setAttribute("playsinline", true); video.play(); requestAnimationFrame(tick); }); function tick() { message.innerText = "فراخوانی ویدئو..." if (video.readyState === video.HAVE_ENOUGH_DATA) { canvasElement.hidden = false; canvasElement.height = video.videoHeight; canvasElement.width = video.videoWidth; canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height); var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height); var code = jsQR(imageData.data, imageData.width, imageData.height, { inversionAttempts: "dontInvert", }); if (code) { drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58"); drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58"); drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58"); drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58"); message.innerText = code.data; } else { message.innerText = "در حال اسکن..."; } } requestAnimationFrame(tick); } </script> </body> </html>
در مثال فوق تابع tick وظیقه شناسایی کیوآرکد را برعهده داشته و drawline کادر قرمز رنگی به دور کیوآرکد پیدا شده، رسم می کند.
حال گام بعدی این است که میخواهیم:
الف) هنگام تشخیص کیوآرکد از تصویر زنده وب کم عکس گرفته شود
ب) محدوده و ابعاد عکس را مشخص کنیم
ج) عکس نهایی را در سرور ذخیره نماییم
<html> <head> <meta charset="utf-8" /> <title>Qrcode</title> <script src="jsQR.js"></script> <script src="croppr.js"></script> <script src="jquery.min.js"></script> <link href="croppr.css" rel="stylesheet" /> </head> <body style="text-align:center"> <h1 style="direction:rtl">اسکن توسط وب کم با توانایی خواندن qrcode</h1> <div id="message">وب کم فعال نیست</div> <button onClick="start_scan()" id="btn_1">شروع</button> <button onClick="save_image()" id="btn_2" hidden>ذخیره</button> <canvas id="canvas" hidden></canvas> <div id="div_img"></div> <script> var video; var canvasElement; var canvas; var message; var qr_stream; var snapshot; var croppr; var x,y,w,h; function drawLine(begin, end, color) { canvas.beginPath(); canvas.moveTo(begin.x, begin.y); canvas.lineTo(end.x, end.y); canvas.lineWidth = 4; canvas.strokeStyle = color; canvas.stroke(); } function start_scan() { video = document.createElement("video"); canvasElement = document.getElementById("canvas"); canvas = canvasElement.getContext("2d"); message = document.getElementById("message"); $('#canvas').show(); $('#div_img').hide(); $('#btn_1').hide(); $('#btn_2').hide(); navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) { video.srcObject = stream; video.setAttribute("playsinline", true); video.play(); qr_stream = stream; requestAnimationFrame(tick); }); } function tick() { message.innerText = "فراخوانی ویدئو..." if (video.readyState === video.HAVE_ENOUGH_DATA) { canvasElement.height = video.videoHeight; canvasElement.width = video.videoWidth; canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height); var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height); var code = jsQR(imageData.data, imageData.width, imageData.height, { inversionAttempts: "dontInvert", }); if (code) { drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58"); drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58"); drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58"); drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58"); message.innerText = code.data; stop_scan(); return; } else { message.innerText = "در حال اسکن..."; } } requestAnimationFrame(tick); } function stop_scan() { qr_stream.getTracks().forEach(function(track) { track.stop(); }); snapshot = canvasElement.toDataURL("image/jpeg"); canvas.clearRect(0, 0, canvasElement.width, canvasElement.height); $('#div_img').html('<img id="cropper" src="" />'); $('#cropper').prop('src',snapshot); $('#canvas').hide(); $('#div_img').show(); $('#btn_1').show(); $('#btn_2').show(); start_crop(); } function start_crop() { croppr = new Croppr('#cropper', { aspectRatio: 1, minSize: [100, 100, 'px'] }); } function save_image() { x = y = w = h = 0; var value = croppr.getValue(); x = value.x; y = value.y; w = value.width; h = value.height; $.ajax({ type: "POST", url: "index_save.php", data: { imgBase64: snapshot, x: x, y: y, w: w, h: h }, success: function(res) { $('#message').html(res); $('#div_img').html('<img id="cropper" src="'+res+'" />'); $('#btn_2').hide(); } }); } </script> </body> </html>
<?php header('Content-Type: text/html; charset=utf-8'); $fileData = explode(',', $_POST['imgBase64']); $file = base64_decode($fileData[1]); $src = imagecreatefromstring($file); $src_x = $_POST['x']; $src_y = $_POST['y']; $src_width = $_POST['w']; $src_height = $_POST['h']; $thumb_width = 300; $thumb_height = 300; $thumb_x = 0; $thumb_y = 0; $thumb = imagecreatetruecolor($thumb_width,$thumb_height); $thumb_title = time().".jpg"; imagecopyresampled($thumb, $src, $thumb_x, $thumb_y, $src_x, $src_y, $thumb_width, $thumb_height, $src_width, $src_height); imagejpeg($thumb, $thumb_title, 80); echo $thumb_title; ?>
در این مثال نیز ابتدا علاوه بر کتابخانه قبلی دو کتابخانه جیکوئری و Croppr را به پروژه خود اضافه میکنیم. کار Croppr این است که به ما امکان تعیین دلخواه محدوده عکس را میدهد تا بتوانیم عکس را برش دهیم.
الف) جهت عکس گرفتن از تصویر وبکم طبق مثال فوق در تابع stop_scan از دستور toDataURL("image/jpeg") استفاده می کنیم؛ مقدار آن محتوای عکس ماست که میتوانیم آن را در نشانی src عکس قرار دهیم.
ب) به کمک Croppr محدوده تصویر را جهت ذخیره کردن مشخص میکنیم. تابع start_crop یک Croppr جدید فراخوانی میکند که در این مثال نسبت تصویر را 1:1 تعیین کردهایم. سپس با دستور croppr.getValue مختصات و ابعاد تصویر برش خورده را به دست میآوریم. در نهایت متغیرهای مختصات و تصویر را توسط آجاکس به سمت سرور ارسال میکنیم.
ج) در سمت سرور مانند فایل index_save.php متغیرها را دریافت کرده و تصویر را با نام دلخواه ذخیره میکنیم.