project done before
This commit is contained in:
83
www/camera_example.html
Normal file
83
www/camera_example.html
Normal file
@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
|
||||
<title>Camera</title>
|
||||
<script type="text/javascript">
|
||||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||
|
||||
function getUserMedia(constraints, success, failure) {
|
||||
navigator.getUserMedia(constraints, function(stream) {
|
||||
var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream;
|
||||
success.apply(null, [videoSrc]);
|
||||
}, failure);
|
||||
}
|
||||
|
||||
|
||||
function initCamera(constraints, video, callback) {
|
||||
getUserMedia(constraints, function (src) {
|
||||
video.src = src;
|
||||
video.addEventListener('loadeddata', function() {
|
||||
var attempts = 10;
|
||||
|
||||
function checkVideo() {
|
||||
if (attempts > 0) {
|
||||
if (video.videoWidth > 0 && video.videoHeight > 0) {
|
||||
console.log(video.videoWidth + "px x " + video.videoHeight + "px");
|
||||
video.play();
|
||||
callback();
|
||||
} else {
|
||||
window.setTimeout(checkVideo, 100);
|
||||
}
|
||||
} else {
|
||||
callback('Unable to play video stream.');
|
||||
}
|
||||
attempts--;
|
||||
}
|
||||
|
||||
checkVideo();
|
||||
}, false);
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
});
|
||||
}
|
||||
|
||||
function copyToCanvas(video, ctx) {
|
||||
( function frame() {
|
||||
ctx.drawImage(video, 0, 0);
|
||||
window.requestAnimationFrame(frame);
|
||||
}());
|
||||
}
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
var constraints = {
|
||||
video: {
|
||||
mandatory: {
|
||||
minWidth: 1280,
|
||||
minHeight: 720
|
||||
}
|
||||
}
|
||||
},
|
||||
video = document.createElement('video'),
|
||||
canvas = document.createElement('canvas');
|
||||
|
||||
document.body.appendChild(video);
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
initCamera(constraints, video, function() {
|
||||
canvas.setAttribute('width', video.videoWidth);
|
||||
canvas.setAttribute('height', video.videoHeight);
|
||||
copyToCanvas(video, canvas.getContext('2d'));
|
||||
});
|
||||
}, false);
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
27
www/config.rb
Normal file
27
www/config.rb
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
# Require any additional compass plugins here.
|
||||
|
||||
|
||||
# Set this to the root of your project when deployed:
|
||||
http_path = "/"
|
||||
css_dir = "css"
|
||||
sass_dir = "sass"
|
||||
images_dir = "img"
|
||||
javascripts_dir = "js"
|
||||
fonts_dir="fonts"
|
||||
|
||||
# You can select your preferred output style here (can be overridden via the command line):
|
||||
# output_style = :expanded or :nested or :compact or :compressed
|
||||
|
||||
# To enable relative paths to assets via compass helper functions. Uncomment:
|
||||
# relative_assets = true
|
||||
|
||||
# To disable debugging comments that display the original location of your selectors. Uncomment:
|
||||
# line_comments = false
|
||||
|
||||
|
||||
# If you prefer the indented syntax, you might want to regenerate this
|
||||
# project again passing --syntax sass, or you can uncomment this:
|
||||
# preferred_syntax = :sass
|
||||
# and then run:
|
||||
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
|
||||
16
www/css/colors.css
Normal file
16
www/css/colors.css
Normal file
@ -0,0 +1,16 @@
|
||||
@charset "UTF-8";
|
||||
/* LESS - http://lesscss.org style sheet */
|
||||
/* Palette color codes */
|
||||
/* Palette URL: http://paletton.com/#uid=31g0q0kHZAviRSkrHLOGomVNzac */
|
||||
/* Feel free to copy&paste color codes to your application */
|
||||
/* MIXINS */
|
||||
/* As hex codes */
|
||||
/* Main Primary color */
|
||||
/* Main Secondary color (1) */
|
||||
/* Main Secondary color (2) */
|
||||
/* As RGBa codes */
|
||||
/* Main Primary color */
|
||||
/* Main Secondary color (1) */
|
||||
/* Main Secondary color (2) */
|
||||
/* Generated by Paletton.com ├é┬® 2002-2014 */
|
||||
/* http://paletton.com */
|
||||
1
www/css/fonts.css
Normal file
1
www/css/fonts.css
Normal file
@ -0,0 +1 @@
|
||||
@import url("https://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600");
|
||||
298
www/css/styles.css
Normal file
298
www/css/styles.css
Normal file
@ -0,0 +1,298 @@
|
||||
@charset "UTF-8";
|
||||
@import url("https://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600");
|
||||
|
||||
body {
|
||||
background-color: #FFF;
|
||||
margin: 0px;
|
||||
font-family: Ubuntu, sans-serif;
|
||||
color: #1e1e1e;
|
||||
font-weight: normal;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-family: "Cabin Condensed", sans-serif;
|
||||
}
|
||||
|
||||
header {
|
||||
background: #FFC600;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
header .headline {
|
||||
max-width: 640px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
header .headline h1 {
|
||||
color: #FFDD69;
|
||||
font-size: 3em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
header .headline h2 {
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
footer {
|
||||
background: #0A4DB7;
|
||||
color: #6C9CE8;
|
||||
padding: 1em 2em 2em;
|
||||
}
|
||||
|
||||
#container {
|
||||
width: 640px;
|
||||
margin: 20px auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#interactive.viewport {
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
}
|
||||
|
||||
|
||||
#interactive.viewport canvas, video {
|
||||
float: left;
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
}
|
||||
|
||||
#interactive.viewport canvas.drawingBuffer, video.drawingBuffer {
|
||||
margin-left: -640px;
|
||||
}
|
||||
|
||||
.controls fieldset {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.controls .input-group {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.controls .input-group input, .controls .input-group button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.controls .reader-config-group {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.controls .reader-config-group label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.controls .reader-config-group label span {
|
||||
width: 9rem;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.controls:after {
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
#result_strip {
|
||||
margin: 10px 0;
|
||||
border-top: 1px solid #EEE;
|
||||
border-bottom: 1px solid #EEE;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
#result_strip > ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
width: auto;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#result_strip > ul > li {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
#result_strip > ul > li .thumbnail {
|
||||
padding: 5px;
|
||||
margin: 4px;
|
||||
border: 1px dashed #CCC;
|
||||
}
|
||||
|
||||
#result_strip > ul > li .thumbnail img {
|
||||
max-width: 140px;
|
||||
}
|
||||
|
||||
#result_strip > ul > li .thumbnail .caption {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#result_strip > ul > li .thumbnail .caption h4 {
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
height: 40px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#result_strip > ul:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.scanner-overlay {
|
||||
display: none;
|
||||
width: 640px;
|
||||
height: 510px;
|
||||
position: absolute;
|
||||
padding: 20px;
|
||||
top: 50%;
|
||||
margin-top: -275px;
|
||||
left: 50%;
|
||||
margin-left: -340px;
|
||||
background-color: #FFF;
|
||||
-moz-box-shadow: #333333 0px 4px 10px;
|
||||
-webkit-box-shadow: #333333 0px 4px 10px;
|
||||
box-shadow: #333333 0px 4px 10px;
|
||||
}
|
||||
|
||||
.scanner-overlay > .header {
|
||||
position: relative;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.scanner-overlay > .header h4, .scanner-overlay > .header .close {
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.scanner-overlay > .header h4 {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.scanner-overlay > .header .close {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
i.icon-24-scan {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzFFMjMzNTBFNjcwMTFFMkIzMERGOUMzMzEzM0E1QUMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzFFMjMzNTFFNjcwMTFFMkIzMERGOUMzMzEzM0E1QUMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDMUUyMzM0RUU2NzAxMUUyQjMwREY5QzMzMTMzQTVBQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMUUyMzM0RkU2NzAxMUUyQjMwREY5QzMzMTMzQTVBQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtQr90wAAAUuSURBVHjanFVLbFRVGP7ua97T9DGPthbamAYYBNSMVbBpjCliWWGIEBMWsnDJxkh8RDeEDW5MDGticMmGBWnSlRSCwgLFNkqmmrRIqzjTznTazkxn5s7c6/efzm0G0Jhwkj/nP+d/nv91tIWFBTQaDQWapkGW67p4ltUub5qmAi0UCqF/a/U2m81tpmddotwwDGSz2dzi4uKSaOucnJycGhsbe1XXdQiIIcdxEAgEtgXq9brySHCht79UXi/8QheawN27d385fPjwuEl6XyKR6LdtW7t06RLK5TKOHj2K/fv3Q87Dw8OYn5/HiRMnMDs7i5mZGQwODiqlPp8PuVwO6XRaOXb16lXl1OnTp5FMJvtosF8M+MWLarWqGJaWlpBKpRRcu3YN4+PjmJ6exsTEhDJw5coVjI6OKgPhcBiZTAbxeBx+vx+XL19Gd3c3Tp48Ka9zqDYgBlTQxYNgMIhIJKLCILkQb+TZsgvdsiyFi+feWRR7oRNZyanQtvW2V4DEUUBiK2eJpeDirSyhCe7F2QPh8fiEp72i9PbsC5G52DbiKZA771yr1dTuGfJ4PQNPFoAyQNR1aNEmsS5eyB3PgjeooMZd2AWvNmzYci/Gea7TeFOcI93jV/K67noGmi4vdRI9gPSDeMLSdKUBZZczlWm1rTtHjLZ24d+WER2tc8N1m+Y+ID74wx0zGYvhg9UNrJdtHJyZRdQfwPsrq9g99xsGlgsYmr6BNzO/IVwsYfjBQ6XYz6JI/72MV366B5/lw0elOkJWGUM3bmKtWjXSLuLaBWhnPnnp0FfoiFi4+TMfVAb2poBkDLjO845uYLEAjL4ALGWBP5YAOsP4AJYBFDaB1HOSVWD2PuV95H2RdV93Lv74/cf6p6Zxq/h6OofeOPJBC39JtONdwOAAViOs4p4OFGTf0Uc8iiyrr9YdQrUnDLsngrVOC0jQib44HlF2RafRZBz1Qy+vfhgK3NJZBlrm+LEm9qWwzFgLU7Ozg0JxZP06jQSRpQ7EerAWDSt6PuhHPmChEAog56fCLvJT5hHTm3OZkz3DyLx7XNWTGEA1GkV14gjWgwbW0ESVjYRwCOuai03L5E7OUBAV4kXSS4auoGIaKOma4m8EA5R1sMEGLh95C+XuLph0WJWpxepYYLtfT0RRgY1KgNODY6BoaChRuEhDCIZQYseuki5KN6hcQHiq7OZNv4/Zq2O6P4Lfkwn46vZjjaYZrIpvWbpzjLErrc4xUGE4avRedpYJalRcIl5hQius/SrPm9xrNOQYJhao6BvNUeWqtY8KaWuNjHOFAr7mM9f4NA4UbKysoUJ8PV9UzVOx6wxDDWUOxnK1pmCD07fOMAvtIsM3l89Dl3HRGhVma9AZMqjOnz2LQqWCxs6dqr3T7x1DTzKJaG8SekcHhg4cgI/56uKdlKnBV/WndqN3YAB/7tyBd3oT6GBIOzs7kc/nDfFdDFT5bS73cp06dQoaPa/Rw/rtO/resTHxxE2m9rCrbSR27UJCcMf1BpiA5rAAGgdfc868fUR1sMwj0cm9Iu9IctweisViB3hhKTHDcHc5jv/LspbyaZrR1OD82/fIlOkuB9LnEWRmDX2TsddUPg3D5gvuc0je0rZaD5EW6G3yjS+A3eeBEWq3XW/Abw1HhUspXADufQb86oW7tZytkYCN//3hHwBvDALPi8EnSOYK8DAOfCc2h4aGcO7cuafkzampqf9UripH12/DtOZbx8ciVGzYy5OO40o25ascGRl5Ssc/AgwAjW3JwqIUjSYAAAAASUVORK5CYII=");
|
||||
display: inline-block;
|
||||
background-repeat: no-repeat;
|
||||
line-height: 24px;
|
||||
margin-top: 1px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
@media (max-width: 603px) {
|
||||
|
||||
#container {
|
||||
width: 300px;
|
||||
margin: 10px auto;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#container form.voucher-form input.voucher-code {
|
||||
width: 180px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 603px) {
|
||||
|
||||
.reader-config-group {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.reader-config-group label > span {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.reader-config-group label > select, .reader-config-group label > input {
|
||||
max-width: calc(50% - 2px);
|
||||
}
|
||||
|
||||
#interactive.viewport {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
#interactive.viewport canvas, video {
|
||||
margin-top: -50px;
|
||||
width: 300px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
#interactive.viewport canvas.drawingBuffer, video.drawingBuffer {
|
||||
margin-left: -300px;
|
||||
}
|
||||
|
||||
|
||||
#result_strip {
|
||||
margin-top: 5px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
#result_strip ul.thumbnails > li {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#result_strip ul.thumbnails > li .thumbnail .imgWrapper {
|
||||
width: 130px;
|
||||
height: 130px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#result_strip ul.thumbnails > li .thumbnail .imgWrapper img {
|
||||
margin-top: -25px;
|
||||
width: 130px;
|
||||
height: 180px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 603px) {
|
||||
|
||||
.overlay.scanner {
|
||||
width: 640px;
|
||||
height: 510px;
|
||||
padding: 20px;
|
||||
margin-top: -275px;
|
||||
margin-left: -340px;
|
||||
background-color: #FFF;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.overlay.scanner > .header {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.overlay.scanner > .header h4, .overlay.scanner > .header .close {
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.overlay.scanner > .header .close {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
11583
www/dist/quagga.js
vendored
Normal file
11583
www/dist/quagga.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
www/dist/quagga.min.js
vendored
Normal file
1
www/dist/quagga.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
112
www/file_input.html
Normal file
112
www/file_input.html
Normal file
@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||
|
||||
<title>index</title>
|
||||
<meta name="description" content=""/>
|
||||
<meta name="author" content="Christoph Oberhofer"/>
|
||||
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0"/>
|
||||
<link rel="stylesheet" type="text/css" href="css/styles.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<div class="headline">
|
||||
<h1>QuaggaJS</h1>
|
||||
|
||||
<h2>An advanced barcode-scanner written in JavaScript</h2>
|
||||
</div>
|
||||
</header>
|
||||
<section id="container" class="container">
|
||||
<h3>Working with file-input</h3>
|
||||
|
||||
<p>This example let's you select an image from your local filesystem.
|
||||
QuaggaJS then tries to decode the barcode using
|
||||
the preferred method (<strong>Code128</strong> or <strong>EAN</strong>).
|
||||
There is no server interaction needed as the
|
||||
file is simply accessed through the <a
|
||||
href="http://www.w3.org/TR/file-upload/">File API</a>.</p>
|
||||
|
||||
<p>This also works great on a wide range of mobile-phones where the camera
|
||||
access through <code>getUserMedia</code> is still very limited.</p>
|
||||
|
||||
<div class="controls">
|
||||
<fieldset class="input-group">
|
||||
<input type="file" accept="image/*" capture="camera"/>
|
||||
<button>Rerun</button>
|
||||
</fieldset>
|
||||
<fieldset class="reader-config-group">
|
||||
<label>
|
||||
<span>Barcode-Type</span>
|
||||
<select name="decoder_readers">
|
||||
<option value="code_128" selected="selected">Code 128</option>
|
||||
<option value="code_39">Code 39</option>
|
||||
<option value="code_39_vin">Code 39 VIN</option>
|
||||
<option value="ean">EAN</option>
|
||||
<option value="ean_extended">EAN-extended</option>
|
||||
<option value="ean_8">EAN-8</option>
|
||||
<option value="upc">UPC</option>
|
||||
<option value="upc_e">UPC-E</option>
|
||||
<option value="codabar">Codabar</option>
|
||||
<option value="i2of5">Interleaved 2 of 5</option>
|
||||
<option value="2of5">Standard 2 of 5</option>
|
||||
<option value="code_93">Code 93</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Resolution (long side)</span>
|
||||
<select name="input-stream_size">
|
||||
<option value="320">320px</option>
|
||||
<option value="640">640px</option>
|
||||
<option selected="selected" value="800">800px</option>
|
||||
<option value="1280">1280px</option>
|
||||
<option value="1600">1600px</option>
|
||||
<option value="1920">1920px</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Patch-Size</span>
|
||||
<select name="locator_patch-size">
|
||||
<option value="x-small">x-small</option>
|
||||
<option value="small">small</option>
|
||||
<option value="medium">medium</option>
|
||||
<option selected="selected" value="large">large</option>
|
||||
<option value="x-large">x-large</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Half-Sample</span>
|
||||
<input type="checkbox" name="locator_half-sample" />
|
||||
</label>
|
||||
<label>
|
||||
<span>Single Channel</span>
|
||||
<input type="checkbox" name="input-stream_single-channel" />
|
||||
</label>
|
||||
<label>
|
||||
<span>Workers</span>
|
||||
<select name="numOfWorkers">
|
||||
<option value="0">0</option>
|
||||
<option selected="selected" value="1">1</option>
|
||||
</select>
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div id="result_strip">
|
||||
<ul class="thumbnails"></ul>
|
||||
</div>
|
||||
<div id="interactive" class="viewport"></div>
|
||||
<div id="debug" class="detection"></div>
|
||||
</section>
|
||||
<footer>
|
||||
<p>
|
||||
© Copyright by Christoph Oberhofer
|
||||
</p>
|
||||
</footer>
|
||||
<script src="vendor/jquery-1.9.0.min.js" type="text/javascript"></script>
|
||||
<script src="../dist/quagga.js" type="text/javascript"></script>
|
||||
<script src="file_input.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
186
www/file_input.js
Normal file
186
www/file_input.js
Normal file
@ -0,0 +1,186 @@
|
||||
$(function() {
|
||||
var App = {
|
||||
init: function() {
|
||||
App.attachListeners();
|
||||
},
|
||||
attachListeners: function() {
|
||||
var self = this;
|
||||
|
||||
$(".controls input[type=file]").on("change", function(e) {
|
||||
if (e.target.files && e.target.files.length) {
|
||||
App.decode(URL.createObjectURL(e.target.files[0]));
|
||||
}
|
||||
});
|
||||
|
||||
$(".controls button").on("click", function(e) {
|
||||
var input = document.querySelector(".controls input[type=file]");
|
||||
if (input.files && input.files.length) {
|
||||
App.decode(URL.createObjectURL(input.files[0]));
|
||||
}
|
||||
});
|
||||
|
||||
$(".controls .reader-config-group").on("change", "input, select", function(e) {
|
||||
e.preventDefault();
|
||||
var $target = $(e.target),
|
||||
value = $target.attr("type") === "checkbox" ? $target.prop("checked") : $target.val(),
|
||||
name = $target.attr("name"),
|
||||
state = self._convertNameToState(name);
|
||||
|
||||
console.log("Value of "+ state + " changed to " + value);
|
||||
self.setState(state, value);
|
||||
});
|
||||
},
|
||||
_accessByPath: function(obj, path, val) {
|
||||
var parts = path.split('.'),
|
||||
depth = parts.length,
|
||||
setter = (typeof val !== "undefined") ? true : false;
|
||||
|
||||
return parts.reduce(function(o, key, i) {
|
||||
if (setter && (i + 1) === depth) {
|
||||
o[key] = val;
|
||||
}
|
||||
return key in o ? o[key] : {};
|
||||
}, obj);
|
||||
},
|
||||
_convertNameToState: function(name) {
|
||||
return name.replace("_", ".").split("-").reduce(function(result, value) {
|
||||
return result + value.charAt(0).toUpperCase() + value.substring(1);
|
||||
});
|
||||
},
|
||||
detachListeners: function() {
|
||||
$(".controls input[type=file]").off("change");
|
||||
$(".controls .reader-config-group").off("change", "input, select");
|
||||
$(".controls button").off("click");
|
||||
},
|
||||
decode: function(src) {
|
||||
var self = this,
|
||||
config = $.extend({}, self.state, {src: src});
|
||||
|
||||
Quagga.decodeSingle(config, function(result) {});
|
||||
},
|
||||
setState: function(path, value) {
|
||||
var self = this;
|
||||
|
||||
if (typeof self._accessByPath(self.inputMapper, path) === "function") {
|
||||
value = self._accessByPath(self.inputMapper, path)(value);
|
||||
}
|
||||
|
||||
self._accessByPath(self.state, path, value);
|
||||
|
||||
console.log(JSON.stringify(self.state));
|
||||
App.detachListeners();
|
||||
App.init();
|
||||
},
|
||||
inputMapper: {
|
||||
inputStream: {
|
||||
size: function(value){
|
||||
return parseInt(value);
|
||||
}
|
||||
},
|
||||
numOfWorkers: function(value) {
|
||||
return parseInt(value);
|
||||
},
|
||||
decoder: {
|
||||
readers: function(value) {
|
||||
if (value === 'ean_extended') {
|
||||
return [{
|
||||
format: "ean_reader",
|
||||
config: {
|
||||
supplements: [
|
||||
'ean_5_reader', 'ean_2_reader'
|
||||
]
|
||||
}
|
||||
}];
|
||||
}
|
||||
return [{
|
||||
format: value + "_reader",
|
||||
config: {}
|
||||
}];
|
||||
}
|
||||
}
|
||||
},
|
||||
state: {
|
||||
inputStream: {
|
||||
size: 800,
|
||||
singleChannel: false
|
||||
},
|
||||
locator: {
|
||||
patchSize: "medium",
|
||||
halfSample: true
|
||||
},
|
||||
decoder: {
|
||||
readers: [{
|
||||
format: "code_128_reader",
|
||||
config: {}
|
||||
}]
|
||||
},
|
||||
locate: true,
|
||||
src: null
|
||||
}
|
||||
};
|
||||
|
||||
App.init();
|
||||
|
||||
function calculateRectFromArea(canvas, area) {
|
||||
var canvasWidth = canvas.width,
|
||||
canvasHeight = canvas.height,
|
||||
top = parseInt(area.top)/100,
|
||||
right = parseInt(area.right)/100,
|
||||
bottom = parseInt(area.bottom)/100,
|
||||
left = parseInt(area.left)/100;
|
||||
|
||||
top *= canvasHeight;
|
||||
right = canvasWidth - canvasWidth*right;
|
||||
bottom = canvasHeight - canvasHeight*bottom;
|
||||
left *= canvasWidth;
|
||||
|
||||
return {
|
||||
x: left,
|
||||
y: top,
|
||||
width: right - left,
|
||||
height: bottom - top
|
||||
};
|
||||
}
|
||||
|
||||
Quagga.onProcessed(function(result) {
|
||||
var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||
drawingCanvas = Quagga.canvas.dom.overlay,
|
||||
area;
|
||||
|
||||
if (result) {
|
||||
if (result.boxes) {
|
||||
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||
result.boxes.filter(function (box) {
|
||||
return box !== result.box;
|
||||
}).forEach(function (box) {
|
||||
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2});
|
||||
});
|
||||
}
|
||||
|
||||
if (result.box) {
|
||||
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
|
||||
}
|
||||
|
||||
if (result.codeResult && result.codeResult.code) {
|
||||
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
|
||||
}
|
||||
|
||||
if (App.state.inputStream.area) {
|
||||
area = calculateRectFromArea(drawingCanvas, App.state.inputStream.area);
|
||||
drawingCtx.strokeStyle = "#0F0";
|
||||
drawingCtx.strokeRect(area.x, area.y, area.width, area.height);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Quagga.onDetected(function(result) {
|
||||
var code = result.codeResult.code,
|
||||
$node,
|
||||
canvas = Quagga.canvas.dom.image;
|
||||
|
||||
$node = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
||||
$node.find("img").attr("src", canvas.toDataURL());
|
||||
$node.find("h4.code").html(code);
|
||||
$("#result_strip ul.thumbnails").prepend($node);
|
||||
});
|
||||
});
|
||||
110
www/html_lama/css/index.css
Normal file
110
www/html_lama/css/index.css
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
* {
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
|
||||
-webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
|
||||
-webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
|
||||
background-color:#E4E4E4;
|
||||
background-image:linear-gradient(to bottom, #A7A7A7 0%, #E4E4E4 51%);
|
||||
font-family: system-ui, -apple-system, -apple-system-font, 'Segoe UI', 'Roboto', sans-serif;
|
||||
font-size:12px;
|
||||
height:100vh;
|
||||
margin:0px;
|
||||
padding:0px;
|
||||
/* Padding to avoid the "unsafe" areas behind notches in the screen */
|
||||
padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
|
||||
text-transform:uppercase;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
/* Portrait layout (default) */
|
||||
.app {
|
||||
background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
|
||||
position:absolute; /* position in the center of the screen */
|
||||
left:50%;
|
||||
top:50%;
|
||||
height:50px; /* text area height */
|
||||
width:225px; /* text area width */
|
||||
text-align:center;
|
||||
padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */
|
||||
margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */
|
||||
/* offset horizontal: half of text area width */
|
||||
}
|
||||
|
||||
/* Landscape layout (with min-width) */
|
||||
@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
|
||||
.app {
|
||||
background-position:left center;
|
||||
padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */
|
||||
margin:-90px 0px 0px -198px; /* offset vertical: half of image height */
|
||||
/* offset horizontal: half of image width and text area width */
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size:24px;
|
||||
font-weight:normal;
|
||||
margin:0px;
|
||||
overflow:visible;
|
||||
padding:0px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.event {
|
||||
border-radius:4px;
|
||||
color:#FFFFFF;
|
||||
font-size:12px;
|
||||
margin:0px 30px;
|
||||
padding:2px 0px;
|
||||
}
|
||||
|
||||
.event.listening {
|
||||
background-color:#333333;
|
||||
display:block;
|
||||
}
|
||||
|
||||
.event.received {
|
||||
background-color:#4B946A;
|
||||
display:none;
|
||||
}
|
||||
|
||||
#deviceready.ready .event.listening { display: none; }
|
||||
#deviceready.ready .event.received { display: block; }
|
||||
|
||||
@keyframes fade {
|
||||
from { opacity: 1.0; }
|
||||
50% { opacity: 0.4; }
|
||||
to { opacity: 1.0; }
|
||||
}
|
||||
|
||||
.blink {
|
||||
animation:fade 3000ms infinite;
|
||||
-webkit-animation:fade 3000ms infinite;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-image:linear-gradient(to bottom, #585858 0%, #1B1B1B 51%);
|
||||
}
|
||||
}
|
||||
BIN
www/html_lama/img/logo.png
Normal file
BIN
www/html_lama/img/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
51
www/html_lama/index.html
Normal file
51
www/html_lama/index.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
Customize this policy to fit your own app's needs. For more guidance, see:
|
||||
https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
|
||||
Some notes:
|
||||
* gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
|
||||
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
|
||||
* Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
|
||||
* Enable inline JS: add 'unsafe-inline' to default-src
|
||||
-->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<link rel="stylesheet" href="css/index.css">
|
||||
<title>Hello World</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<h1>Apache Cordova</h1>
|
||||
<div id="deviceready" class="blink">
|
||||
<p class="event listening">Connecting to Device</p>
|
||||
<p class="event received">Device is Ready</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="cordova.js"></script>
|
||||
<script src="js/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
29
www/html_lama/js/index.js
Normal file
29
www/html_lama/js/index.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// Wait for the deviceready event before using any of Cordova's device APIs.
|
||||
// See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready
|
||||
document.addEventListener('deviceready', onDeviceReady, false);
|
||||
|
||||
function onDeviceReady() {
|
||||
// Cordova is now initialized. Have fun!
|
||||
|
||||
console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
|
||||
document.getElementById('deviceready').classList.add('ready');
|
||||
}
|
||||
126
www/index.html
Normal file
126
www/index.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
|
||||
<title>index</title>
|
||||
<meta name="description" content="" />
|
||||
<meta name="author" content="Christoph Oberhofer" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
|
||||
<link rel="stylesheet" type="text/css" href="css/styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<div class="headline">
|
||||
<h1>QuaggaJS</h1>
|
||||
<h2>An advanced barcode-scanner written in JavaScript</h2>
|
||||
</div>
|
||||
</header>
|
||||
<section id="container" class="container">
|
||||
<h3>The user's camera</h3>
|
||||
<p>If your platform supports the <strong>getUserMedia</strong> API call, you can try the real-time locating and decoding features.
|
||||
Simply allow the page to access your web-cam and point it to a barcode. You can switch between <strong>Code128</strong>
|
||||
and <strong>EAN</strong> to test different scenarios.
|
||||
It works best if your camera has built-in auto-focus.
|
||||
</p>
|
||||
<div class="controls">
|
||||
<fieldset class="input-group">
|
||||
<button class="stop">Stop</button>
|
||||
</fieldset>
|
||||
<fieldset class="reader-config-group">
|
||||
<label>
|
||||
<span>Barcode-Type</span>
|
||||
<select name="decoder_readers">
|
||||
<option value="code_128" selected="selected">Code 128</option>
|
||||
<option value="code_39">Code 39</option>
|
||||
<option value="code_39_vin">Code 39 VIN</option>
|
||||
<option value="ean">EAN</option>
|
||||
<option value="ean_extended">EAN-extended</option>
|
||||
<option value="ean_8">EAN-8</option>
|
||||
<option value="upc">UPC</option>
|
||||
<option value="upc_e">UPC-E</option>
|
||||
<option value="codabar">Codabar</option>
|
||||
<option value="i2of5">Interleaved 2 of 5</option>
|
||||
<option value="2of5">Standard 2 of 5</option>
|
||||
<option value="code_93">Code 93</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Resolution (width)</span>
|
||||
<select name="input-stream_constraints">
|
||||
<option value="320x240">320px</option>
|
||||
<option selected="selected" value="640x480">640px</option>
|
||||
<option value="800x600">800px</option>
|
||||
<option value="1280x720">1280px</option>
|
||||
<option value="1600x960">1600px</option>
|
||||
<option value="1920x1080">1920px</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Patch-Size</span>
|
||||
<select name="locator_patch-size">
|
||||
<option value="x-small">x-small</option>
|
||||
<option value="small">small</option>
|
||||
<option selected="selected" value="medium">medium</option>
|
||||
<option value="large">large</option>
|
||||
<option value="x-large">x-large</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Half-Sample</span>
|
||||
<input type="checkbox" checked="checked" name="locator_half-sample" />
|
||||
</label>
|
||||
<label>
|
||||
<span>Workers</span>
|
||||
<select name="numOfWorkers">
|
||||
<option value="0">0</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option selected="selected" value="4">4</option>
|
||||
<option value="8">8</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Camera</span>
|
||||
<select name="input-stream_constraints" id="deviceSelection">
|
||||
</select>
|
||||
</label>
|
||||
<button onclick ='hidupkan_kembali()'>heheheh</button>
|
||||
<label style="display: none">
|
||||
<span>Zoom</span>
|
||||
<select name="settings_zoom"></select>
|
||||
</label>
|
||||
<label style="display: none">
|
||||
<span>Torch</span>
|
||||
<input type="checkbox" name="settings_torch" />
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div id="result_strip">
|
||||
<ul class="thumbnails"></ul>
|
||||
<ul class="collector"></ul>
|
||||
</div>
|
||||
<div id="interactive" class="viewport"></div>
|
||||
</section>
|
||||
<footer>
|
||||
<p>
|
||||
© Made with ❤️ by Christoph Oberhofer
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<script src="vendor/jquery-1.9.0.min.js" type="text/javascript"></script>
|
||||
<script src="http://webrtc.github.io/adapter/adapter-latest.js" type="text/javascript"></script>
|
||||
<script src="cordova.js"></script>
|
||||
<script src="index.js"></script>
|
||||
<script src="dist/quagga.js" type="text/javascript"></script>
|
||||
<script src="live_w_locator.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
function hidupkan_kembali() {
|
||||
App.init();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
33
www/index.js
Normal file
33
www/index.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// Wait for the deviceready event before using any of Cordova's device APIs.
|
||||
// See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready
|
||||
document.addEventListener('deviceready', onDeviceReady, false);
|
||||
// var permissions = cordova.plugins.permissions; permissions.checkPermission(permissions.CAMERA, (res) => { if (!res.hasPermission) { permissions.requestPermission(permissions.CAMERA, open());
|
||||
|
||||
|
||||
function onDeviceReady() {
|
||||
// Cordova is now initialized. Have fun!
|
||||
console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
|
||||
// var permissions = cordova.plugins.permissions; permissions.checkPermission(permissions.CAMERA, (res) => { if (!res.hasPermission) { permissions.requestPermission(permissions.CAMERA, open());
|
||||
App.init();
|
||||
// console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
|
||||
// document.getElementById('deviceready').classList.add('ready');
|
||||
}
|
||||
299
www/live_w_locator.js
Normal file
299
www/live_w_locator.js
Normal file
@ -0,0 +1,299 @@
|
||||
// $(function() {
|
||||
var resultCollector = Quagga.ResultCollector.create({
|
||||
capture: true,
|
||||
capacity: 20,
|
||||
blacklist: [{
|
||||
code: "WIWV8ETQZ1", format: "code_93"
|
||||
}, {
|
||||
code: "EH3C-%GU23RK3", format: "code_93"
|
||||
}, {
|
||||
code: "O308SIHQOXN5SA/PJ", format: "code_93"
|
||||
}, {
|
||||
code: "DG7Q$TV8JQ/EN", format: "code_93"
|
||||
}, {
|
||||
code: "VOFD1DB5A.1F6QU", format: "code_93"
|
||||
}, {
|
||||
code: "4SO64P4X8 U4YUU1T-", format: "code_93"
|
||||
}],
|
||||
filter: function(codeResult) {
|
||||
// only store results which match this constraint
|
||||
// e.g.: codeResult
|
||||
return true;
|
||||
}
|
||||
});
|
||||
var App = {
|
||||
init: function() {
|
||||
var self = this;
|
||||
|
||||
Quagga.init(this.state, function(err) {
|
||||
if (err) {
|
||||
return self.handleError(err);
|
||||
}
|
||||
//Quagga.registerResultCollector(resultCollector);
|
||||
App.attachListeners();
|
||||
App.checkCapabilities();
|
||||
Quagga.start();
|
||||
});
|
||||
},
|
||||
handleError: function(err) {
|
||||
console.log(err);
|
||||
},
|
||||
checkCapabilities: function() {
|
||||
var track = Quagga.CameraAccess.getActiveTrack();
|
||||
var capabilities = {};
|
||||
if (typeof track.getCapabilities === 'function') {
|
||||
capabilities = track.getCapabilities();
|
||||
}
|
||||
this.applySettingsVisibility('zoom', capabilities.zoom);
|
||||
this.applySettingsVisibility('torch', capabilities.torch);
|
||||
},
|
||||
updateOptionsForMediaRange: function(node, range) {
|
||||
console.log('updateOptionsForMediaRange', node, range);
|
||||
var NUM_STEPS = 6;
|
||||
var stepSize = (range.max - range.min) / NUM_STEPS;
|
||||
var option;
|
||||
var value;
|
||||
while (node.firstChild) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
for (var i = 0; i <= NUM_STEPS; i++) {
|
||||
value = range.min + (stepSize * i);
|
||||
option = document.createElement('option');
|
||||
option.value = value;
|
||||
option.innerHTML = value;
|
||||
node.appendChild(option);
|
||||
}
|
||||
},
|
||||
applySettingsVisibility: function(setting, capability) {
|
||||
// depending on type of capability
|
||||
if (typeof capability === 'boolean') {
|
||||
var node = document.querySelector('input[name="settings_' + setting + '"]');
|
||||
if (node) {
|
||||
node.parentNode.style.display = capability ? 'block' : 'none';
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (window.MediaSettingsRange && capability instanceof window.MediaSettingsRange) {
|
||||
var node = document.querySelector('select[name="settings_' + setting + '"]');
|
||||
if (node) {
|
||||
this.updateOptionsForMediaRange(node, capability);
|
||||
node.parentNode.style.display = 'block';
|
||||
}
|
||||
return;
|
||||
}
|
||||
},
|
||||
initCameraSelection: function(){
|
||||
var streamLabel = Quagga.CameraAccess.getActiveStreamLabel();
|
||||
|
||||
return Quagga.CameraAccess.enumerateVideoDevices()
|
||||
.then(function(devices) {
|
||||
function pruneText(text) {
|
||||
return text.length > 30 ? text.substr(0, 30) : text;
|
||||
}
|
||||
var $deviceSelection = document.getElementById("deviceSelection");
|
||||
while ($deviceSelection.firstChild) {
|
||||
$deviceSelection.removeChild($deviceSelection.firstChild);
|
||||
}
|
||||
devices.forEach(function(device) {
|
||||
var $option = document.createElement("option");
|
||||
$option.value = device.deviceId || device.id;
|
||||
$option.appendChild(document.createTextNode(pruneText(device.label || device.deviceId || device.id)));
|
||||
$option.selected = streamLabel === device.label;
|
||||
$deviceSelection.appendChild($option);
|
||||
});
|
||||
});
|
||||
},
|
||||
attachListeners: function() {
|
||||
var self = this;
|
||||
|
||||
self.initCameraSelection();
|
||||
$(".controls").on("click", "button.stop", function(e) {
|
||||
e.preventDefault();
|
||||
Quagga.stop();
|
||||
self._printCollectedResults();
|
||||
});
|
||||
|
||||
$(".controls .reader-config-group").on("change", "input, select", function(e) {
|
||||
e.preventDefault();
|
||||
var $target = $(e.target),
|
||||
value = $target.attr("type") === "checkbox" ? $target.prop("checked") : $target.val(),
|
||||
name = $target.attr("name"),
|
||||
state = self._convertNameToState(name);
|
||||
|
||||
console.log("Value of "+ state + " changed to " + value);
|
||||
self.setState(state, value);
|
||||
});
|
||||
},
|
||||
_printCollectedResults: function() {
|
||||
var results = resultCollector.getResults(),
|
||||
$ul = $("#result_strip ul.collector");
|
||||
|
||||
results.forEach(function(result) {
|
||||
var $li = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
||||
|
||||
$li.find("img").attr("src", result.frame);
|
||||
$li.find("h4.code").html(result.codeResult.code + " (" + result.codeResult.format + ")");
|
||||
$ul.prepend($li);
|
||||
});
|
||||
},
|
||||
_accessByPath: function(obj, path, val) {
|
||||
var parts = path.split('.'),
|
||||
depth = parts.length,
|
||||
setter = (typeof val !== "undefined") ? true : false;
|
||||
|
||||
return parts.reduce(function(o, key, i) {
|
||||
if (setter && (i + 1) === depth) {
|
||||
if (typeof o[key] === "object" && typeof val === "object") {
|
||||
Object.assign(o[key], val);
|
||||
} else {
|
||||
o[key] = val;
|
||||
}
|
||||
}
|
||||
return key in o ? o[key] : {};
|
||||
}, obj);
|
||||
},
|
||||
_convertNameToState: function(name) {
|
||||
return name.replace("_", ".").split("-").reduce(function(result, value) {
|
||||
return result + value.charAt(0).toUpperCase() + value.substring(1);
|
||||
});
|
||||
},
|
||||
detachListeners: function() {
|
||||
$(".controls").off("click", "button.stop");
|
||||
$(".controls .reader-config-group").off("change", "input, select");
|
||||
},
|
||||
applySetting: function(setting, value) {
|
||||
var track = Quagga.CameraAccess.getActiveTrack();
|
||||
if (track && typeof track.getCapabilities === 'function') {
|
||||
switch (setting) {
|
||||
case 'zoom':
|
||||
return track.applyConstraints({advanced: [{zoom: parseFloat(value)}]});
|
||||
case 'torch':
|
||||
return track.applyConstraints({advanced: [{torch: !!value}]});
|
||||
}
|
||||
}
|
||||
},
|
||||
setState: function(path, value) {
|
||||
var self = this;
|
||||
|
||||
if (typeof self._accessByPath(self.inputMapper, path) === "function") {
|
||||
value = self._accessByPath(self.inputMapper, path)(value);
|
||||
}
|
||||
|
||||
if (path.startsWith('settings.')) {
|
||||
var setting = path.substring(9);
|
||||
return self.applySetting(setting, value);
|
||||
}
|
||||
self._accessByPath(self.state, path, value);
|
||||
|
||||
//console.log(JSON.stringify(self.state));
|
||||
App.detachListeners();
|
||||
Quagga.stop();
|
||||
App.init();
|
||||
},
|
||||
inputMapper: {
|
||||
inputStream: {
|
||||
constraints: function(value){
|
||||
if (/^(\d+)x(\d+)$/.test(value)) {
|
||||
var values = value.split('x');
|
||||
return {
|
||||
width: {min: parseInt(values[0])},
|
||||
height: {min: parseInt(values[1])}
|
||||
};
|
||||
}
|
||||
return {
|
||||
deviceId: value
|
||||
};
|
||||
}
|
||||
},
|
||||
numOfWorkers: function(value) {
|
||||
return parseInt(value);
|
||||
},
|
||||
decoder: {
|
||||
readers: function(value) {
|
||||
if (value === 'ean_extended') {
|
||||
return [{
|
||||
format: "ean_reader",
|
||||
config: {
|
||||
supplements: [
|
||||
'ean_5_reader', 'ean_2_reader'
|
||||
]
|
||||
}
|
||||
}];
|
||||
}
|
||||
return [{
|
||||
format: value + "_reader",
|
||||
config: {}
|
||||
}];
|
||||
}
|
||||
}
|
||||
},
|
||||
state: {
|
||||
inputStream: {
|
||||
type : "LiveStream",
|
||||
constraints: {
|
||||
width: {min: 640},
|
||||
height: {min: 480},
|
||||
facingMode: "environment",
|
||||
aspectRatio: {min: 1, max: 2}
|
||||
}
|
||||
},
|
||||
locator: {
|
||||
patchSize: "medium",
|
||||
halfSample: true
|
||||
},
|
||||
numOfWorkers: 2,
|
||||
frequency: 10,
|
||||
decoder: {
|
||||
readers : [{
|
||||
format: "ean_reader",
|
||||
config: {}
|
||||
}]
|
||||
},
|
||||
locate: true
|
||||
},
|
||||
lastResult : null
|
||||
};
|
||||
|
||||
App.init();
|
||||
|
||||
Quagga.onProcessed(function(result) {
|
||||
|
||||
var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||
drawingCanvas = Quagga.canvas.dom.overlay;
|
||||
|
||||
if (result) {
|
||||
if (result.boxes) {
|
||||
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||
result.boxes.filter(function (box) {
|
||||
return box !== result.box;
|
||||
}).forEach(function (box) {
|
||||
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2});
|
||||
});
|
||||
}
|
||||
|
||||
if (result.box) {
|
||||
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
|
||||
}
|
||||
|
||||
if (result.codeResult && result.codeResult.code) {
|
||||
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Quagga.onDetected(function(result) {
|
||||
var code = result.codeResult.code;
|
||||
console.log(code);
|
||||
Quagga.stop();
|
||||
if (App.lastResult !== code) {
|
||||
App.lastResult = code;
|
||||
var $node = null, canvas = Quagga.canvas.dom.image;
|
||||
|
||||
$node = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
||||
$node.find("img").attr("src", canvas.toDataURL());
|
||||
$node.find("h4.code").html(code);
|
||||
$("#result_strip ul.thumbnails").prepend($node);
|
||||
}
|
||||
});
|
||||
|
||||
// });
|
||||
27
www/node-test-with-buffer.js
Normal file
27
www/node-test-with-buffer.js
Normal file
@ -0,0 +1,27 @@
|
||||
var Quagga = require('../lib/quagga').default;
|
||||
|
||||
var buffer = require('fs').readFileSync('../test/fixtures/code_128/image-001.jpg');
|
||||
|
||||
decode(buffer);
|
||||
function decode(buff){
|
||||
Quagga.decodeSingle({
|
||||
src: buff,
|
||||
numOfWorkers: 0,
|
||||
inputStream: {
|
||||
mime: "image/jpeg",
|
||||
size: 800,
|
||||
area: {
|
||||
top: "10%",
|
||||
right: "5%",
|
||||
left: "5%",
|
||||
bottom: "10%"
|
||||
}
|
||||
}
|
||||
}, function(result) {
|
||||
if (result.codeResult) {
|
||||
console.log("result", result.codeResult.code);
|
||||
} else {
|
||||
console.log("not detected");
|
||||
}
|
||||
});
|
||||
}
|
||||
21
www/node-test.js
Normal file
21
www/node-test.js
Normal file
@ -0,0 +1,21 @@
|
||||
var Quagga = require('../lib/quagga').default;
|
||||
|
||||
Quagga.decodeSingle({
|
||||
src: "../test/fixtures/code_128/image-001.jpg",
|
||||
numOfWorkers: 0,
|
||||
inputStream: {
|
||||
size: 800,
|
||||
area: {
|
||||
top: "10%",
|
||||
right: "5%",
|
||||
left: "5%",
|
||||
bottom: "10%"
|
||||
}
|
||||
}
|
||||
}, function(result) {
|
||||
if(result.codeResult) {
|
||||
console.log("result", result.codeResult.code);
|
||||
} else {
|
||||
console.log("not detected");
|
||||
}
|
||||
});
|
||||
69
www/static_images.html
Normal file
69
www/static_images.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
|
||||
<title>index</title>
|
||||
<meta name="description" content="" />
|
||||
<meta name="author" content="Christoph Oberhofer" />
|
||||
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0" />
|
||||
<link href='http://fonts.googleapis.com/css?family=Ubuntu:400,700,300' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="css/styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<div class="headline">
|
||||
<h1>QuaggaJS</h1>
|
||||
<h2>An advanced barcode-scanner written in JavaScript</h2>
|
||||
</div>
|
||||
</header>
|
||||
<section id="container" class="container">
|
||||
<h3>Working with static images</h3>
|
||||
<p>This examples uses static image files as input which are loaded from the server on startup.
|
||||
The locating and decoding process takes place inside the browser.
|
||||
Hit the <strong>next</strong> button to try a different image. You can also switch between
|
||||
two different test-sets. Each of those contains 10 images, demonstrating the capabilities of decoding
|
||||
<strong>Code128</strong> and <strong>EAN</strong> encoded barcodes.
|
||||
</p>
|
||||
<div class="controls">
|
||||
<fieldset class="input-group">
|
||||
<button class="next">Next</button>
|
||||
</fieldset>
|
||||
<fieldset class="reader-config-group">
|
||||
<span>Barcode-Type</span>
|
||||
<select name="decoder_readers;input-stream_src">
|
||||
<option value="code_128" selected="selected">Code 128</option>
|
||||
<option value="code_39">Code 39</option>
|
||||
<option value="code_39_vin">Code 39 VIN</option>
|
||||
<option value="ean">EAN</option>
|
||||
<option value="ean_extended">EAN-extended</option>
|
||||
<option value="ean_8">EAN-8</option>
|
||||
<option value="upc">UPC</option>
|
||||
<option value="upc_e">UPC-E</option>
|
||||
<option value="codabar">Codabar</option>
|
||||
<option value="i2of5">I2of5</option>
|
||||
<option value="i2of5">Interleaved 2 of 5</option>
|
||||
<option value="2of5">Standard 2 of 5</option>
|
||||
<option value="code_93">Code 93</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div id="result_strip">
|
||||
<ul class="thumbnails"></ul>
|
||||
</div>
|
||||
<div id="interactive" class="viewport"></div>
|
||||
<div id="debug" class="detection"></div>
|
||||
</section>
|
||||
<footer>
|
||||
<p>
|
||||
© Copyright by Christoph Oberhofer
|
||||
</p>
|
||||
</footer>
|
||||
<script src="vendor/jquery-1.9.0.min.js" type="text/javascript"></script>
|
||||
<script src="../dist/quagga.js" type="text/javascript"></script>
|
||||
<script src="static_images.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
170
www/static_images.js
Normal file
170
www/static_images.js
Normal file
@ -0,0 +1,170 @@
|
||||
$(function() {
|
||||
var App = {
|
||||
init: function() {
|
||||
var config = this.config[this.state.decoder.readers[0].format] || this.config.default;
|
||||
config = $.extend(true, {}, config, this.state);
|
||||
Quagga.init(config, function() {
|
||||
App.attachListeners();
|
||||
Quagga.start();
|
||||
});
|
||||
},
|
||||
config: {
|
||||
"default": {
|
||||
inputStream: { name: "Test",
|
||||
type: "ImageStream",
|
||||
length: 10,
|
||||
size: 800
|
||||
},
|
||||
locator: {
|
||||
patchSize: "medium",
|
||||
halfSample: true
|
||||
}
|
||||
},
|
||||
"i2of5_reader": {
|
||||
inputStream: {
|
||||
size: 800,
|
||||
type: "ImageStream",
|
||||
length: 5
|
||||
},
|
||||
locator: {
|
||||
patchSize: "small",
|
||||
halfSample: false
|
||||
}
|
||||
}
|
||||
},
|
||||
attachListeners: function() {
|
||||
var self = this;
|
||||
|
||||
$(".controls").on("click", "button.next", function(e) {
|
||||
e.preventDefault();
|
||||
Quagga.start();
|
||||
});
|
||||
|
||||
$(".controls .reader-config-group").on("change", "input, select", function(e) {
|
||||
e.preventDefault();
|
||||
var $target = $(e.target),
|
||||
value = $target.attr("type") === "checkbox" ? $target.prop("checked") : $target.val(),
|
||||
name = $target.attr("name"),
|
||||
states = self._convertNameToStates(name);
|
||||
|
||||
console.log("Value of "+ states + " changed to " + value);
|
||||
self.setState(states, value);
|
||||
});
|
||||
},
|
||||
detachListeners: function() {
|
||||
$(".controls").off("click", "button.next");
|
||||
$(".controls .reader-config-group").off("change", "input, select");
|
||||
},
|
||||
_accessByPath: function(obj, path, val) {
|
||||
var parts = path.split('.'),
|
||||
depth = parts.length,
|
||||
setter = (typeof val !== "undefined") ? true : false;
|
||||
|
||||
return parts.reduce(function(o, key, i) {
|
||||
if (setter && (i + 1) === depth) {
|
||||
o[key] = val;
|
||||
}
|
||||
return key in o ? o[key] : {};
|
||||
}, obj);
|
||||
},
|
||||
_convertNameToStates: function(names) {
|
||||
return names.split(";").map(this._convertNameToState.bind(this));
|
||||
},
|
||||
_convertNameToState: function(name) {
|
||||
return name.replace("_", ".").split("-").reduce(function(result, value) {
|
||||
return result + value.charAt(0).toUpperCase() + value.substring(1);
|
||||
});
|
||||
},
|
||||
setState: function(paths, value) {
|
||||
var self = this;
|
||||
|
||||
paths.forEach(function(path) {
|
||||
var mappedValue;
|
||||
|
||||
if (typeof self._accessByPath(self.inputMapper, path) === "function") {
|
||||
mappedValue = self._accessByPath(self.inputMapper, path)(value);
|
||||
}
|
||||
self._accessByPath(self.state, path, mappedValue);
|
||||
});
|
||||
|
||||
console.log(JSON.stringify(self.state));
|
||||
App.detachListeners();
|
||||
Quagga.stop();
|
||||
App.init();
|
||||
},
|
||||
inputMapper: {
|
||||
decoder: {
|
||||
readers: function(value) {
|
||||
if (value === 'ean_extended') {
|
||||
return [{
|
||||
format: "ean_reader",
|
||||
config: {
|
||||
supplements: [
|
||||
'ean_5_reader', 'ean_2_reader'
|
||||
]
|
||||
}
|
||||
}];
|
||||
}
|
||||
return [{
|
||||
format: value + "_reader",
|
||||
config: {}
|
||||
}];
|
||||
}
|
||||
},
|
||||
inputStream: {
|
||||
src: function(value) {
|
||||
return "../test/fixtures/" + value + "/"
|
||||
}
|
||||
}
|
||||
},
|
||||
state: {
|
||||
inputStream: {
|
||||
src: "../test/fixtures/code_128/"
|
||||
},
|
||||
decoder : {
|
||||
readers : [{
|
||||
format: "code_128_reader",
|
||||
config: {}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
App.init();
|
||||
window.App = App;
|
||||
|
||||
Quagga.onProcessed(function(result) {
|
||||
var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||
drawingCanvas = Quagga.canvas.dom.overlay;
|
||||
|
||||
if (result) {
|
||||
if (result.boxes) {
|
||||
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||
result.boxes.filter(function (box) {
|
||||
return box !== result.box;
|
||||
}).forEach(function (box) {
|
||||
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2});
|
||||
});
|
||||
}
|
||||
|
||||
if (result.box) {
|
||||
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
|
||||
}
|
||||
|
||||
if (result.codeResult && result.codeResult.code) {
|
||||
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Quagga.onDetected(function(result) {
|
||||
var $node,
|
||||
canvas = Quagga.canvas.dom.image,
|
||||
detectedCode = result.codeResult.code;
|
||||
|
||||
$node = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
||||
$node.find("img").attr("src", canvas.toDataURL());
|
||||
$node.find("h4.code").html(detectedCode);
|
||||
$("#result_strip ul.thumbnails").prepend($node);
|
||||
});
|
||||
});
|
||||
4
www/vendor/jquery-1.9.0.min.js
vendored
Normal file
4
www/vendor/jquery-1.9.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user