// original by http://lach.la var pixelSize = 2; var blockSize = (3*pixelSize); var image; var has_image = false; var has_canvas = false; var qr, controls function halftoneQR(QRBytes, controlBytes, image) { var canvas = $('#output').get(0); var ctx = canvas.getContext('2d'); drawPixel(); ctx.fillStyle = '#fff' ctx.fillRect(0, 0, canvas.width, canvas.height); var canvasThreshold = $('#imageThreshold').get(0); var ctxThreshold = canvasThreshold.getContext('2d'); 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 === '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 byteRow = 0; byteRow < controlBytes.length; byteRow++) { for (var byteCell = 0; byteCell < controlBytes[byteRow].length; byteCell++) { if (controlBytes[byteRow][byteCell] !== null) { if (controlBytes[byteRow][byteCell] === true) { ctx.fillStyle = 'black'; } else { ctx.fillStyle = 'white'; } ctx.fillRect(byteRow * blockSize, byteCell * blockSize, blockSize, blockSize); } }; }; $('#download').attr('href', $('#output').get(0).toDataURL()); } function drawImage() { var canvasColour = $('#imageColour').get(0); var ctxColour = canvasColour.getContext('2d'); ctxColour.clearRect(0,0,canvasColour.width, canvasColour.height); ctxColour.drawImage(image, 0, 0, canvasColour.width, canvasColour.height); console.log('hi') drawPixel(); } function drawPixel() { var canvasColour = $('#imageColour').get(0); var canvasPixel = $('#imagePixel').get(0); var ctxPixel = canvasPixel.getContext('2d'); var canvasTemp = document.createElement('canvas'); canvasTemp.width = canvasTemp.height = (canvasPixel.width / pixelSize); var ctxTemp = canvasTemp.getContext('2d'); ctxPixel.imageSmoothingEnabled = ctxPixel.mozImageSmoothingEnabled = ctxPixel.msImageSmoothingEnabled = ctxPixel.webkitImageSmoothingEnabled = ctxTemp.imageSmoothingEnabled = ctxTemp.mozImageSmoothingEnabled = ctxTemp.msImageSmoothingEnabled = ctxTemp.webkitImageSmoothingEnabled = false; ctxTemp.drawImage(canvasColour, 0, 0, canvasTemp.width, canvasTemp.height); ctxPixel.drawImage(canvasTemp, 0, 0, canvasPixel.width, canvasPixel.height); drawThreshold(); } function drawThreshold() { var canvasPixel = $('#imagePixel').get(0); var ctxPixel = canvasPixel.getContext('2d'); var canvasThreshold = $('#imageThreshold').get(0); var ctxThreshold = canvasThreshold.getContext('2d'); var pixels = ctxPixel.getImageData(0,0,canvasPixel.width,canvasPixel.height); var d = pixels.data; var width = Math.sqrt(d.length / 4) / pixelSize; for (var i=0; i= 127) ? 255 : 0; //d[i] = d[i+1] = d[i+2] = v; d[i] = d[i+1] = d[i+2] = grey; } for (var i=0; i= 127) ? 255 : 0; // Dithering var error = (grey - v) / 8; var i2 = i / 4; var row = Math.floor(i2 / width); var cell = i2 % width; d[i] = d[i+1] = d[i+2] = v; d[(((row + 0) * width) + (cell + 1)) * 4] = d[(((row + 0) * width) + (cell + 1)) * 4 + 1] = d[(((row + 0) * width) + (cell + 1)) * 4 + 2] = d[(((row + 0) * width) + (cell + 1)) * 4] + error; d[(((row + 0) * width) + (cell + 2)) * 4] = d[(((row + 0) * width) + (cell + 2)) * 4 + 1] = d[(((row + 0) * width) + (cell + 2)) * 4 + 2] = d[(((row + 0) * width) + (cell + 2)) * 4] + error; d[(((row + 1) * width) + (cell - 1)) * 4] = d[(((row + 1) * width) + (cell - 1)) * 4 + 1] = d[(((row + 1) * width) + (cell - 1)) * 4 + 2] = d[(((row + 1) * width) + (cell - 1)) * 4] + error; d[(((row + 1) * width) + (cell + 0)) * 4] = d[(((row + 1) * width) + (cell + 0)) * 4 + 1] = d[(((row + 1) * width) + (cell + 0)) * 4 + 2] = d[(((row + 1) * width) + (cell + 0)) * 4] + error; d[(((row + 1) * width) + (cell + 1)) * 4] = d[(((row + 1) * width) + (cell + 1)) * 4 + 1] = d[(((row + 1) * width) + (cell + 1)) * 4 + 2] = d[(((row + 1) * width) + (cell + 1)) * 4] + error; d[(((row + 2) * width) + (cell + 0)) * 4] = d[(((row + 2) * width) + (cell + 0)) * 4 + 1] = d[(((row + 2) * width) + (cell + 0)) * 4 + 2] = d[(((row + 2) * width) + (cell + 0)) * 4] + error; } ctxThreshold.putImageData(pixels, 0, 0); } function generate() { var text = $('#input').val() || "http://asdf.us/"; var errorLevel = 'H'; var sizes = { L: [152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 1240], M: [128, 224, 352, 512, 688, 864, 992, 700, 700, 524], Q: [104, 176, 272, 384, 286, 608, 508, 376, 608, 434], H: [72, 128, 208, 288, 214, 480, 164, 296, 464, 346] }; var userSize = parseInt($('#size').val()); var QRsize = -1; if (userSize === 0) { for (var i = 0; i < sizes[errorLevel].length; i++) { if (text.length < sizes[errorLevel][i]) { QRsize = i + 1; break; } }; } else { if (text.length < sizes[errorLevel][userSize - 1]) { QRsize = userSize; } } if (QRsize == -1) { if (userSize === 0) { if (errorLevel === 'H') { alert('Too much text.'); } else { alert('Too much text. Try decreasing the error level.'); } } else { alert('Too much text. Try decreasing the error level or increasing the size.'); } return; } qr = qrcode(QRsize, errorLevel); qr.addData(text); qr.make(); controls = qrcode(QRsize, errorLevel); controls.addData(text); controls.make(true); } function render(){ halftoneQR(qr.returnByteArray(), controls.returnByteArray()); } $("#file_upload").on('change', function(e){ e.preventDefault(); var files = e.originalEvent.dataTransfer ? e.originalEvent.dataTransfer.files : e.originalEvent.target.files; var file = files[0]; var reader = new FileReader(); reader.onload = function(event) { //event.target.result; var imageColour = new Image(); imageColour.onload = function() { has_image = true; image = this; drawImage() render() } imageColour.src = event.target.result; }; reader.readAsDataURL(file); return false; }) $("#input").on('input', function(){ generate() if ($("#size").val() === 'auto') { resize() } render() }) $("#error_level").on('change', function(){ generate() render() }) $("#size").on('change', function(){ generate() resize() render() }) function resize(){ var canvas = $('#output').get(0); canvas.width = canvas.height = qr.returnByteArray().length * (3*pixelSize); var ctx = canvas.getContext('2d'); $('#imageColour, #imageThreshold, #imagePixel').attr({ width: canvas.width, height: canvas.height }) } $(function() { generate() resize() render() })