Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
52 lines (47 sloc) 4.33 KB
---
layout: post
title: 'qrquine: a QR code based quine'
permalink: '/qrquine/'
tags: ['qrcode', 'quine', 'javascript', 'size optimization', 'code golf']
---
<div class="lead">
<p>
Have you ever tried to embed a QR code inside a QR code?
</p>
<p>
Quines are little programs which produce copies of themselves. I figured it would be fun and challenging to try to make a QR code quine.
</p>
<p>
My QR code contains a piece of javascript which is able to re-generate the same QR code. The javascript is encoded as a data URI. The javascript code reads itself
(via location.href) and then generates the same QR code image, ad infinitum.
</p>
<p>
I started with <a href="https://github.com/jeromeetienne/jquery-qrcode/blob/master/src/qrcode.js">Jerome Etienne's qrcode.js</a> library,
and rewrote the code in a size optimized way. I had to do this because QR codes can only contain a limited number of bytes. My final code is roughly 20x smaller (from ~28,000 to ~1,500 bytes)!
</p>
</div>
<section>
<img src="/files/2013/qrquine/qrquine.png">
<br><br><p>Note: some older devices may have trouble scanning large images (due to poor camera quality). I tested this image with an iPhone 5S. When I scan the QR code, I get a blob of data starting with "data:text/html,...". I can then copy-paste this data into Safari and I get the same image back. If your device can't scan the QR code, you can try using
<a href="http://blog.qr4.nl/Online-QR-Code_Decoder.aspx">an online QR code service</a>.
</p>
</section>
<section>
<div class="page-header"><h3>The javascript</h3></div>
<p>Here is the data which is embedded in the above image.</p>
<p><a href="https://github.com/alokmenghrajani/alokmenghrajani.github.com/tree/355a521ee3a44d8e00684a0b5252ad935f0e22fb/qrquine/work">You can also trace the steps I took to achieve this.</a></p>
<pre>
data:text/html,&lt;body style=padding:9&gt;&lt;canvas id=C&gt;&lt;script&gt;function P(r,c,v){I[A*r+c]=v;return!(v&amp;&amp;C.getContext('2d').fillRect(c*3,r*3,3,3))}function S(i,j){for(r=O;r&lt;8;r++)for(c=O;c&lt;8;c++)j+c&gt;O&amp;&amp;j+c&lt;A&amp;&amp;P(i+r,j+c,0&lt;r&amp;&amp;(r&lt;7&amp;&amp;!(c%6))||((c+1)%8&amp;&amp;!(r%6)||1&lt;r&amp;&amp;(r&lt;5&amp;&amp;(1&lt;c&amp;&amp;c&lt;5))))}function N(a,b){if(a[L]&lt;b[L])return a;o=a[0]/b[0];for(i=0;i&lt;b[L];a[i++]^=z){m=b[i];n=o;for(z=0;m;n&gt;255&amp;&amp;(n^=285))m&amp;1&amp;&amp;(z^=n),n&lt;&lt;=1,m&gt;&gt;=1;}a.shift();return N(a,b)}C.height=C.width=(A=133)*3;I=[];X=O=-1;L='length';S(0,0);S(A-7,0);S(i=0,A-7);for(B=[6,30,54,78,102,126];i&lt;6;i++)for(j=0;j&lt;6;j++)if(!I[A*B[i]+B[j]])for(r=-2;r&lt;3;r++)for(c=-2;c&lt;3;c++)P(B[i]+r,B[j]+c,r&amp;&amp;!(r%2)||c&amp;&amp;!(c%2)||!r&amp;&amp;!c);for(i=8;i&lt;A-8;P(6,i++,j))j=!(i%2),P(i,6,j);for(i=0;i&lt;15;i++)j=29427&gt;&gt;i&amp;1,i&lt;6&amp;&amp;P(i,8,j)||i&lt;8&amp;&amp;P(i+1,8,j)||P(118+i,8,j),i&lt;8&amp;&amp;P(8,A-i-1,j)||i&lt;9&amp;&amp;P(8,15-i,j)||P(8,14-i,j);P(A-8,8,1);for(i=0;i&lt;18;P(i%3+A-11,i++/3|0,k))k=119615&gt;&gt;i&amp;1,P(i/3|0,i%3+A-11,k);for(D=[4,i=0,6,0,6];i&lt;1542;D=D.concat([j&gt;&gt;4,j&amp;15]))j=unescape(location.href).charCodeAt(i++);D.push(r=0);for(E=3262;D[L]&lt;E;D=D.concat([1,1]))D=D.concat([14,12]);F=[];for(Z=k=r=0;r&lt;14;r++){i=116+(r&gt;6);l=[];for(j=0;j&lt;i;F[r+j*14-(j&gt;115?7:0)]=l[j++])l[j]=(D[k++]&lt;&lt;4)|D[k++];l=l.concat(new Array(30));for(j=0;j&lt;30;j++)F[r+j*14+1631]=N(l,[1,212,246,77,73,195,192,75,98,5,70,103,177,22,217,138,51,181,246,72,25,18,46,228,74,216,195,11,106,130,150])[j]}Y=7;for(x=i=A-1;i&gt;0;i-=2){for(i==6&amp;&amp;i--;x&gt;O&amp;&amp;x&lt;A;x+=X)for(j=0;j&lt;2;j++)if(I[A*x+i-j]==B[9])k=Z&lt;F[L]&amp;&amp;F[Z]&gt;&gt;Y&amp;1,P(x,i-j,x%2?k:!k),--Y&lt;0&amp;&amp;(Z++,Y=7);x-=X;X=-X}console.log('-- Alok')&lt;/script&gt;</pre>
</section>
<section>
<h3>links</h3>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Quine_(computing)">Read more about quines</a></li>
<li><a href="https://github.com/jeromeetienne/jquery-qrcode/blob/master/src/qrcode.js">Open source qrcode library in JS</a></li>
<li><a href="http://en.wikipedia.org/wiki/QR_code">Information about QR codes</a></li>
<li><a href="http://www.qrcode.com/en/about/version.html">More information about QR codes</a></li>
</ul>
<small>
The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/)
</small>
</section>