Halftone QR Code Generator
HTML
<!-- Licence: MIT -->
<h1>Halftone QR Code Generator</h1>
<h2>Drop an image into your browser, then click generate.</h2>
QR content:<br />
<textarea id="input" cols="50" rows="5">Kitty!</textarea><br />
Redundancy (error correction level):
<select id="error_level">
<option value="L">Low (7%)</option>
<option value="M">Medium (15%)</option>
<option value="Q">Quartile (25%)</option>
<option value="H" selected>High (30%)</option>
</select><br />
QR size:
<select id="size">
<option value="0">Auto</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6" selected>6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
</select> (6 gives the largest blank square area)<br />
Background Type:
<select id="background">
<option value="image" selected>Image</option>
<option value="noise">Noise</option>
<option value="trans">Transparent</option>
</select><br />
<input type="button" id="go" value="Generate" /><br />
<canvas id="imageColour"></canvas>
<canvas id="imagePixel"></canvas>
<canvas id="imageThreshold"></canvas>
<a id="download" href="about:blank" download="qr.png" target="_blank" title="Download QR Code"><canvas id="output"></canvas></a><br />
<a href="http://lach.la">By Lachlan</a>. Licence: <a href="http://www.opensource.org/licenses/mit-license.php">MIT</a>
<br /><br />
Cat photo by Cayambe [<a href="http://creativecommons.org/licenses/by-sa/3.0">CC-BY-SA-3.0</a> or <a href="http://www.gnu.org/copyleft/fdl.html">GFDL</a>], <a href="http://commons.wikimedia.org/wiki/File%3ACat_close-up_2004_b.jpg">via Wikimedia Commons</a>
<div id="overlay">Drop image</div>
CSS
html, body {
height: 100%;
margin: 0;
}
body {
position: relative;
}
h1, h2 {
margin: 0;
}
#overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
z-index: 10;
font-size: 100px;
color: white;
text-align: center;
}
body.hover #overlay {
display: block;
}
canvas {
margin: 5px;
box-shadow: 0 0 5px black;
}
/* Hidden for now */
#imagePixel {
display: none;
}
#output {
background-color: grey;
}
</style>
<script>
//---------------------------------------------------------------------
//
// QR Code Generator for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license.php
//
// The word 'QR Code' is registered trademark of
// DENSO WAVE INCORPORATED
// http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------
var qrcode = function() {
//---------------------------------------------------------------------
// qrcode
//---------------------------------------------------------------------
/**
* qrcode
* @param typeNumber 1 to 10
* @param errorCorrectLevel 'L','M','Q','H'
*/
var qrcode = function(typeNumber, errorCorrectLevel) {
var PAD0 = 0xEC;
var PAD1 = 0x11;
var _typeNumber = typeNumber;
var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];
var _modules = null;
var _moduleCount = 0;
var _dataCache = null;
var _dataList = new Array();
var _this = {};
var makeImpl = function(test, maskPattern, onlyControl) {
onlyControl = onlyControl || false;
_moduleCount = _typeNumber * 4 + 17;
_modules = function(moduleCount) {
var modules = new Array(moduleCount);
for (var row = 0; row < moduleCount; row += 1) {
modules[row] = new Array(moduleCount);
for (var col = 0; col...
JavaScript
var pixelSize = 2;
var blockSize = (3*pixelSize);
var image;
var has_image = false;
function halftoneQR(QRBytes, controlBytes, image) {
var canvas = $('#output').get(0);
canvas.width = canvas.height = QRBytes.length * (3*pixelSize);
var ctx = canvas.getContext('2d');
var background = $('#background').val();
$('#imageColour, #imageThreshold, #imagePixel').attr({
width: canvas.width,
height: canvas.height
});
if (has_image) {
// Re-draw image (incase size changed)
drawImage();
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
var canvasThreshold = $('#imageThreshold').get(0);
var ctxThreshold = canvasThreshold.getContext('2d');
if (has_image && background === 'image') {
ctx.drawImage(canvasThreshold, 0, 0, canvas.width, canvas.height);
}
for (var byteRow = 0; byteRow < QRBytes.length; byteRow++) {
for (var byteCell = 0; byteCell < QRBytes[byteRow].length; byteCell++) {
if ((background === 'image' && !has_image) || background === 'noise') {
// Draw random bytes
ctx.fillStyle = 'black';
for (var subRow = 0; subRow < 3; subRow++) {
for (var subCell = 0; subCell < 3; subCell++) {
ctx.fillStyle = 'black';
if (Math.random() < 0.5) {
ctx.fillStyle = 'white';
}
ctx.fillRect(byteRow * blockSize + (subRow * pixelSize), byteCell * blockSize + (subCell * pixelSize), pixelSize, pixelSize);
}
}
}
// Middle Cell
ctx.fillStyle = QRBytes[byteRow][byteCell] ? 'black' : 'white';
ctx.fillRect(byteRow * blockSize + pixelSize, byteCell * blockSize + pixelSize, pixelSize, pixelSize);
}
}
// Re-draw control bytes
for (var...