qrquine

Have you ever tried to embed a QR code inside a QR code?

Quines are little programs which produce copies of themselves. I figured it would be fun and challenging to try to make a QR code based quine. 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. It reads itself (location.href) and then encodes the same image, ad infinitum.

I started with Jerome Etienne's qrcode.js library, and size optimized the code by a factor 10 (from ~28000 bytes to less than 2500).



Note: my phone is unable to scan this code because of the poor camera resolution. You can however feed the image to an online QR code service. If time permits, I'll try to shave a few hundred more bytes and drop into a smaller QR code version.

Here is the data which is embedded in the above image.

data:text/html,<body style=padding:9><canvas id=q><script>function fs(r,c,v){v&&cx.fillRect(c*3,r*3,3,3);id[3*C*c+r]=v}function fi(i,j){for(r=-1;r<8;r++)if(i+r>-1&&C>i+r)for(c=-1;c<8;c++)fs(i+r,j+c,0<r&&(r<7&&!(c%6))||((c+1)%8&&!(r%6)||1<r&&(r<5&&(1<c&&c<5))))}Z=[];Y=[];for(i=0;i<8;i++)Z[i]=1<<i;for(i=8;i<512;i++)for(j=4;j<9;j++)if(j-7)Z[i]^=Z[i-j];for(i=0;i<255;Y[Z[i]]=i++);function P(n,shift){la=n[L];for(o=0;o<la&&n[o]==0;)o++;this.n=new Array(la-o+shift);for(ia=0;ia<la-o;ia++)this.n[ia]=n[ia+o]}function N(T,e){n=[];for(ib=0;ib<T.n[L];ib++)for(j=0;j<e.n[L];j++)n[ib+j]^=Z[Y[T.n[ib]]+Y[e.n[j]]];return new P(n,0)}function M(T,e){if(T.n[L]-e.n[L]<0)return T;n=[];for(i=0;i<T.n[L];i++)n[i]=T.n[i];for(i=0;i<e.n[L];i++)n[i]^=Z[Y[e.n[i]]+Y[T.n[0]]-Y[e.n[0]]];return M(new P(n,0),e)}function BP(n,l){for(ic=0;ic<l;ic++)Bp(n>>>l-ic-1&1)}function Bp(bit){ie=Math.floor(this.l/8);if(bf[L]<=ie)bf.push(0);if(bit)bf[ie]|=128>>>this.l%8;l++}bf=[];C=165;L="length";q.height=q.width=C*3;cx=q.getContext("2d");id=[];fi(0,0);fi(C-7,0);fi(l=i=0,C-7);po=[6,28,54,80,106,132,158];for(;i<7;i++)for(j=0;j<7;j++)if(!id[3*C*po[j]+po[i]])for(r=-2;r<3;r++)for(c=-2;c<3;c++)fs(po[i]+r,po[j]+c,r&&!(r%2)||(c&&!(c%2)||!r&&!c));a=[];for(i=8;i<C-8;i++){a[i]|=1-i%2;fs(i,6,a[i]);fs(6,i,a[i])}for(i=0;i<15;i++){m=30877>>i&1;if(i<6)fs(i,8,m);else if(i<8)fs(i+1,8,m);else fs(C-15+i,8,m);if(i<8)fs(8,C-i-1,m);else if(i<9)fs(8,15-i,m);else fs(8,15-i-1,m)}fs(C-8,8,1);for(i=0;i<18;i++){m=152622>>i&1;a=Math.floor(i/3);b=i%3+C-11;fs(a,b,m);fs(b,a,m)}rB=[];for(j=0;j<17;j++)rB.push({tc:152,dc:122});for(j=0;j<4;j++)rB.push({tc:153,dc:123});d=location.href;BP(4,4);BP(2518,16);for(i=0;i<2518;i++)BP(d.charCodeAt(i),8);tt=2566;if(l+3<tt*8)BP(0,4);for(;l%8;)Bp(0);for(;;){if(l>=tt*8)break;BP(236,8);if(l>=tt*8)break;BP(17,8)}oa=eX=dX=0;dd=[];ed=[];for(r=0;r<rB[L];r++){dC=rB[r].dc;eC=rB[r].tc-dC;dX=Math.max(dX,dC);eX=Math.max(eX,eC);dd[r]=[];for(i=0;i<dC;i++)dd[r][i]=bf[i+oa];oa+=dC;p=new P([1],0);for(i=0;i<eC;i++)p=N(p,new P([1,Z[i]],0));l=p.n[L]-1;q=new P(dd[r],l);m=M(q,p);ed[r]=[];for(i=0;i<l;i++){j=i+m.n[L]-l;ed[r][i]=j>=0?m.n[j]:0}}D=[];for(Bi=j=i=0;i<dX;i++)for(r=0;r<rB[L];r++)if(i<dd[r][L])D[j++]=dd[r][i];for(i=0;i<eX;i++)for(r=0;r<rB[L];r++)if(i<ed[r][L])D[j++]=ed[r][i];iN=-1;bi=7;for(ro=co=C-1;co>0;co-=2)for(co==6&&co--;;){for(c=0;c<2;c++)if(id[3*C*(co-c)+ro]==null){d=0;if(Bi<D[L])d=D[Bi]>>>bi&1;if(!((ro+co-c)%3))d=!d;fs(ro,co-c,d);bi--;if(bi<0){Bi++;bi=7}}ro+=iN;if(ro<0||C<=ro){ro-=iN;iN=-iN;break}}console.log("-- Alok")</script>

links

The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/)