Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
    <head>
        <meta charset=utf-8 />
        <title>JS Bin</title>
    </head>
    <body>  <span id='ditheringstats'>With Dithering</span>
        <br>
        <canvas id="dither" width="300" height="150"></canvas>
        <br>
<span id='noditheringstats'>No Dithering</span>
        <br>
        <canvas id="nodither" width="300" height="150"></canvas>
        <br>
<span id='originalstats'>Original</span>
        <br>
        <canvas id="original" width="300" height="150"></canvas>
        <br>
        <script>
            window.addEventListener('DOMContentLoaded', function() {
                var ditheringstats = document.querySelector('#ditheringstats');
                var noditheringstats = document.querySelector('#noditheringstats');
                function drawTest(canvas) {
                    canvas = document.querySelector(canvas);
                    var context = canvas.getContext('2d');
                    context.rect(0, 0, canvas.width, canvas.height);
                    var grd = context.createRadialGradient(238, 50, 10, 238, 50, 300);
                    grd.addColorStop(0, '#11FF00');
                    grd.addColorStop(1, '#004CB3');
                    context.fillStyle = grd;
                    context.fill();
                    var grd = context.createRadialGradient(0, 50, 50, 238, 50, 30);
                    grd.addColorStop(0, '#ffFF00');
                    grd.addColorStop(1, '#ff00ff');
                    context.fillStyle = grd;
                    context.fill();
                    var grd = context.createRadialGradient(10, 50, 50, 138, 50, 30);
                    grd.addColorStop(0, '#ff55ff');
                    grd.addColorStop(1, '#000066');
                    context.fillStyle = grd;
                    context.fill();
                }
                drawTest('#original');
                // For those that dont know, the following tag tells Js Bin to put the code  from the js panel where that 
                %code%
                drawTest('#nodither');
                var t = Date.now();
                notdithered = Bitmap('#nodither');
                notdithered.createIndexedData(true);
                noditheringstats.innerText = 'No Dithering - ' + (Date.now() - t);
                notdithered.putImageData();
            })
        </script>
        <script>
            function Bitmap(args) {
                if (this instanceof Bitmap) {
                    if (typeof this.init == "function")
                        this.init.apply(this, args.callee ? args : arguments);
                } else
                    return new Bitmap(arguments);
            };
            Bitmap.prototype.init = function(canvas) {
                if (typeof canvas == 'string') var canvas = document.documentElement.querySelector(canvas);
                this.canvas = canvas;
                this.context = canvas.getContext("2d");
                this.width = canvas.width;
                this.height = canvas.height;
                this.imageData = this.context.getImageData(0, 0, this.width, this.height);
                this.data = this.imageData.data;
                this.reduceColor = {};
                this.rgbData = null;
                this.Data = null;
                this.rgbMode = false;
                this.pixelWidth = 4;
                this.indexedData = null;
                this.indexedPalette = []; // dam this could get big ;P
                this.cachedColors = {};
            };
            Bitmap.prototype.getPixel = function(x, y, iNdEx) {
                if (this.pixelWidth == 1) {
                    var idx = this.indexedData[x + (y * this.width)] * 3;
                    return iNdEx ? idx : [this.indexedPalette[idx], this.indexedPalette[idx + 1], this.indexedPalette[idx + 2]];
                } else {
                    var idx = (x + y * this.width) * this.pixelWidth;
                    var data = this.pixelWidth == 3 ? this.rgbData : this.data;
                    return this.pixelWidth == 3 ? [data[idx], data[idx + 1], data[idx + 2]] : [data[idx], data[idx + 1], data[idx + 2], data[idx + 3]];
                }
            };
            Bitmap.prototype.setPixel = function(x, y, color, iNdEx) {
                if (color[0] > 255) color[0] = 255;
                else if (color[0] < 0) color[0] = 0;
                if (color[1] > 255) color[1] = 255;
                else if (color[1] < 0) color[1] = 0;
                if (color[2] > 255) color[2] = 255;
                else if (color[2] < 0) color[2] = 0;
                if (this.pixelWidth == 1) {
                    if (!iNdEx) color = this.findPaletteColor(color);
                    this.indexedData[x + (y * this.width)] = color;
                } else {
                    var idx = (x + y * this.width) * this.pixelWidth;
                    var data = this.pixelWidth == 3 ? this.rgbData : this.data;
                    data[idx] = color[0];
                    data[idx + 1] = color[1];
                    data[idx + 2] = color[2];
                    if (this.pixelWidth == 4) data[idx + 3] = color[3];
                };
            }
            Bitmap.prototype.putImageData = function(context) {
                var data = this.imageData;
                if (this.pixelWidth == 3) {
                    var canvas = document.createElement('canvas');
                    canvas.width = this.width;
                    canvas.height = this.height;
                    var imageData = canvas.getContext("2d").createImageData(this.width, this.height);
                    data = imageData.data;
                    var dest = 0;
                    var len = data.length;
                    for (var i = 0; i < len; i += 4) {
                        data[i] = this.rgbData[dest++];
                        data[i + 1] = this.rgbData[dest++];
                        data[i + 2] = this.rgbData[dest++];
                        data[i + 3] = 255;
                    }
                    data = imageData;
                }
                if (this.pixelWidth == 1) {
                    var canvas = document.createElement('canvas');
                    canvas.width = this.width;
                    canvas.height = this.height;
                    var imageData = canvas.getContext("2d").createImageData(this.width, this.height);
                    data = imageData.data;
                    var dest = 0;
                    var len = data.length;
                    var idx = null;
                    for (var i = 0; i < len; i += 4) {
                        idx = this.indexedData[dest++] * 3;
                        data[i] = this.indexedPalette[idx];
                        data[i + 1] = this.indexedPalette[idx + 1];
                        data[i + 2] = this.indexedPalette[idx + 2];
                        data[i + 3] = 255;
                    }
                    data = imageData;
                }
                if (context) context.putImageData(data, 0, 0);
                else this.context.putImageData(data, 0, 0);
            };
            Bitmap.prototype.createRgbData = function(matte, transparent) {
                this.rgbData = new Uint8Array(this.width * this.height * 3);
                var pixels = [];
                var count = 0;
                var len = this.data.length;
                for (var i = 0; i < len; i += 4) {
                    var r = this.data[i];
                    var g = this.data[i + 1];
                    var b = this.data[i + 2];
                    var a = this.data[i + 3];
                    if (transparent && a === 0) {
                        // Use transparent color
                        r = transparent[0];
                        g = transparent[1];
                        b = transparent[2];
                        thereAreTransparentPixels = true;
                    } else if (matte && a < 255) {
                        // Use matte with "over" blend mode
                        r = ((r * a + (matte[0] * (255 - a))) / 255) | 0;
                        g = ((g * a + (matte[1] * (255 - a))) / 255) | 0;
                        b = ((b * a + (matte[2] * (255 - a))) / 255) | 0;
                    }
                    this.rgbData[count++] = r;
                    this.rgbData[count++] = g;
                    this.rgbData[count++] = b;
                }
            };
            Bitmap.prototype.createIndexedData = function(auto) {
                if (!this.rgbData) this.createRgbData();
                this.cachedColors = {};
                var pixels = this.rgbData;
                var len /*int*/ = this.rgbData.length;
                var nPix /*int*/ = len / 3;
                this.indexedData = new Array(nPix);
                var opts = {
                    colors: 256, // desired palette size
                    method: 1, // histogram method, 2: min-population threshold within subregions; 1: global top-population
                    boxSize: [64, 64], // subregion dims (if method = 2)
                    boxPxls: 2, // min-population threshold (if method = 2)
                    initColors: 4096, // # of top-occurring colors  to start with (if method = 1)
                    minHueCols: 0, // # of colors per hue group to evaluate regardless of counts, to retain low-count hues
                };
                var q = new RgbQuant(opts);
                q.sample(this.rgbData);
                var p = q.palette();
                for (var i = 0, end = p.length, off = 0; i < end; i = i + 4) {
                    this.indexedPalette[off++] = p[i];
                    this.indexedPalette[off++] = p[i + 1];
                    this.indexedPalette[off++] = p[i + 2];
                }
                // map image pixels to new palette
                var k /*int*/ = 0;
                for (var j /*int*/ = 0; j < nPix; j++) {
                    var index = this.findPaletteColor([pixels[k++], pixels[k++], pixels[k++]]);
                    this.indexedData[j] = index;
                }
                if (auto) this.pixelWidth = 1;
            };
            Bitmap.prototype.createIndexedDataNQ = function(auto) {
                if (!this.rgbData) this.createRgbData();
                var pixels = this.rgbData;
                var len /*int*/ = this.rgbData.length;
                var nPix /*int*/ = len / 3;
                this.indexedData = new Array(nPix);
                var nq /*NeuQuant*/ = new NeuQuant(this.rgbData, len, 10); // 10 is the sample/quality
                this.indexedPalette = nq.process(); // create reduced palette
                // map image pixels to new palette
                var k /*int*/ = 0;
                for (var j /*int*/ = 0; j < nPix; j++) {
                    var index = this.findPaletteColor([pixels[k++], pixels[k++], pixels[k++]]);
                    this.indexedData[j] = index;
                }
                if (auto) this.pixelWidth = 1;
            };
            Bitmap.prototype.save = function() {
                window.open(this.canvas.toDataURL());
            }
            /**
             * Returns index of palette color closest to color
             *
             */
            Bitmap.prototype.findPaletteColor = function(color) {
                if (this.indexedPalette == null) return -1;
                var r /*int*/ = color[0];
                var g /*int*/ = color[1];
                var b /*int*/ = color[2];
                var c = b | (g << 8) | (r << 16);
                if (this.cachedColors[c]) return this.cachedColors[c];
                var minpos /*int*/ = 0;
                var dmin /*int*/ = 256 * 256 * 256 * 256;
                var len /*int*/ = this.indexedPalette.length;
                for (var i /*int*/ = 0; i < len; i = i + 3) {
                    var dr /*int*/ = r - this.indexedPalette[i];
                    var dg /*int*/ = g - this.indexedPalette[i + 1];
                    var db /*int*/ = b - this.indexedPalette[i + 2];
                    var d /*int*/ = dr * dr + dg * dg + db * db;
                    var index /*int*/ = i / 3;
                    if ( /*usedEntry[index] && */ (d < dmin)) {
                        dmin = d;
                        minpos = index;
                    }
                }
                this.cachedColors[c] = minpos;
                return minpos;
            }
            Bitmap.prototype.findExactPaletteColor = function(color) {
                if (this.indexedPalette == null) return -1;
                var len /*int*/ = this.indexedPalette.length;
                for (var i /*int*/ = 0; i < len; i = i + 3) {
                    var dr /*int*/ = this.indexedPalette[i];
                    var dg /*int*/ = this.indexedPalette[i + 1];
                    var db /*int*/ = this.indexedPalette[i + 2];
                    if (dr == color[0] && dg == color[1] && db == color[2]) return i / 3;
                }
                return undefined;
            }
        </script>
        <!-- Quant's -->
        <script>
            eval((function(s) {
                var a, c, e, i, j, o = "",
                    r, t = "¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ#$'@^`";
                for (i = 0; i < s.length; i++) {
                    r = t + s[i][2];
                    a = s[i][1].split("");
                    for (j = a.length - 1; j >= 0; j--) {
                        s[i][0] = s[i][0].split(r.charAt(j)).join(a[j]);
                    }
                    o += s[i][0];
                }
                var p = 6663;
                var x = function(r) {
                    var c, p, s, l = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789';
                    if (r < 63) c = l.charAt(r);
                    else {
                        r -= 63;
                        p = Math.floor(r / 63);
                        s = r % 63;
                        c = l.charAt(p) + l.charAt(s)
                    }
                    return c;
                };
                a = o.substr(p).split(':');
                r = a[1].split('?');
                a = a[0].split('?');
                o = o.substr(0, p);
                if (!''.replace(/^/, String)) {
                    var z = {};
                    for (i = 0; i < 134; i++) {
                        var y = x(i);
                        z[y] = r[i] || y
                    }
                    t = /\b\w\w?\b/g;
                    y = function(a) {
                        return z[a] || a
                    };
                    o = o.replace(t, y);
                } else {
                    for (j = a[a.length - 1] - 1; j >= 0; j--) {
                        if (r[j]) o = o.replace(new RegExp('\b' + (j < 63 ? c.charAt(j) : c.charAt((j - 63) / 63) + c.charAt((j - 63) % 63)) + '\b', 'g'), r[j])
                    }
                }
                return o.replace(//g, "\n").replace(//g, "\"");
            })([
                ["(B(B t(ttôÑ{}¥z´zÑ2¥j´jÑbg¥t´tÑ4096¥F´FÑ.05¥G´GÑ.02¥f´f0´02´2i´iÑ0,J.Zi?aE i(¦f¥i#¥w´wÑ[64,64]¥P´PÑ2¥e=!1¥nó¥a=[]¥c=[]¥gó¥Bó¥AóÂi£¦lô¥LÊ¥kó±æ;r<t;r¼)¦k[rµ{aU:0,aY:[]}¦u=0Âr¤rØaQ.sqrt(p*t*t+x*i*i+g*r*r)ÂsÀiÁtû®sÊÐ-tÞeÊÈt[2®n=p*r*r+x*s*s+g*e*eØn/65025Âe¤s¬eß,a¸têiêsêeÚ¤sÃn=aQ.m¤sÃh=(e+n)/2,e==n)a=o=07{ar(uí-n,o=h>.5?u/(2-e-n):u/(e+nÃe9 t:a=(i-s)/u+(i<s?6:0¾i:a=(s-t)/u+2 s:a=(t-i)/u+4}a/=6}K{h:a,s:o,l:r¤s)}ÂnÀ1/iÉr/2t>=1-sÑt<=s)Ø0³e=1;e<i;e¼¬ní*rt>=n-s&&t<=n+s)Øe}Âa² tÂo² tÂh² a9." +
                        "W.to÷§N(t).bc(8,æ)Âu(t¬i=h(Jû])Number=ÊÑ÷³rÉ{},e=J._ß»n<e;nÖr=J[n®!s&&0!==s)s[rµn7;á×-s'}7{V s6(B² t'á§m(i)-s§m(r)'}Âf(¬t=abcdefghijklmnopqrstuvwxyzKxyzvwtursopqmnklhijfgdeabc=ô.split()§J©{Kèrþ-èiþ'.jo()Âc£V r,s,eÇoà{9HTMLÎdocument.createÅ(a8Ãr§q´q,r§C´CÉçÃs.drawÎ(t,0,0ÝHTMLCñrÑtÉsÑçÝCñRendergï2D:s=sÑt,r=rÑs§8øgetÎData(0,0,r§q,r§CÝÎData:eíÑtßí.data,ií§q9ao¿tÝab:9Ut8ClampedÕt,a=Ôn§DÝah:a=aÑtß=nÑ¿a§DÃiÊÑa._,o=a._/i}K{can:r,ctx:s,imgd:e,buf8:n,aO:a,aq:i,aC:o" +
                        "}Âl¤r,s³eô%rßÊ%s,aô-e,oÊ-n,hu»u<i;u+=s)³f»f<t;f+=r)hú{x:f,y:u,w:f==a?e:r,h:u==o?n:s'ØhÂv¤r¬sôøy*i+s.xß=(s.y+s.hæ)*i+(s.x+s.wæÃa=0,oÊ-s.w+1,hído r§N(J,hÃh+=0==¼a%s.w?o:1while(h<=n)ÂdÀ[]³sät)rús)Øm§N(r,B(r,sØi?tå-t:t-tå'}t.W§7=B£X(¦e)bbCa7 additional images, aØalready assembled.$r=c(t,i)î9 1:¦T(r§O¾2:¦S(r§O,r§q)}},t.W.=B£X(!¦e)¦H()iÊÑ1±c(tÃs=r§Oø_ß=1=Ê?ÔeÛao(e#,a»a<e;a¼¬o=s[a]n[aµ1=Ê?¦R(oÛ¦d(o#}Ø1=Ê?¿n§DÛn:aW¢H«X(!¦e¬tn,i=d(t,!0)0=Ê._)bbNothg has been `d, aØcbe built.î9 1:±¦" +
                        "tÉi[ræ®eô[s®nÊ.bc(0,rÃa=r,oÊ._;a<o&&t[i[a]µí;)núi[a¼])½V(n¾2:V nÊ}n=n§6(B²+t'¥1(n)¥5()¥e=!0}¢KªØ¦H(Ãt?¦a:¿Ô¦c)§D)¢1ªV i´6(B²õ3¹8,â]}ÃrÊ._,e=rßóa_F,e>¦jY(;e>¦j;³aö¼¬hÊ[o®u=Ïh)³f=o+1;f<r;f¼¬cÊ[f®lô[f]c¬v=100*s(h,c)v<a_)aú[év]Ãn[lµu,delete i[f®e--}7;}7;}a_+G}X(e<¦jm§N(a,B£Øi[3]-t[3]'³d»e<¦j;)i[a[d]û]µa[d]Þe¼,d¼}}±i._,öÖi[o])¦aúi[o])¥cúÏ)¥g[ϵ¦c._æ¥B[ϵϥA[ϵi[o]7;³pän¬xd(p)¦g[pµx¥B[pµ¦c[x]¥A[pµ¦a[x]}¢Tª³i,rnÉt._,e»e<s;eÖiô[eüi)>>24º½M(i)iär)r×¼7 r[iµ1}7;¢S=BÀ¦wû®swÞe=r*sß=l(i,t._" +
                        "/ÜÃan,o=Jnr¬sßÚ(aQ.round(r.w*r.h/e)*o§P,2Ãhóv(r,i,B(iºsô[iüs)>>24ºo.Z)o.Z§M(s)säa)aå¼7 X(sähº¼hå>=n)a[sµhå}7 h[sµ1}'}ýV(a)¢5ò=Jthis§c§J©{V s´g[i®h´g[r®u´a[s®f´a[h®cí(uû®uÞu[2]Ãlí(fû®fÞf[2]Ãv=uûµ=uÐ&&u[1µ=uý(cd=fûµ=fÐ&&f[1µ=fý(lp=d-vp)K-p$x=o(+l.lÆ-o(+c.lÆx)K-x$g=a(+l.sÆ-a(+c.sÆg)K-g7 Øvoid 0'¥c§v©{t§a´A[i®t§g[iµr'¢RªV id(t)ئc×¢dªV iB[t]i)ئg׳r,r,e=1e3ß=õ3¹8,â®aa._,o»oo¼¬h=s(n¥a[o])h<e)e=h,r=o}Ør},i.W§MªX(¦u=l+1)¦M«}$i=ay&t,r=(a3¹8Éâ,aÊ==r&&r==s?æ:n(e(Ü).h¥lÃok[a®hLo§" +
                        "U¼,!(o§U>h)ºo§U==h)¦u¼o§U<=h)¦k[a]§Yút)}},i.W§Vª³i=æ;i<¦l;iÖ¦kקU<L)à{9aoiºæ=´m(i))túi)'a9iº!t×)t[iµ17 t×¼'}}$p=.2126,x=.7152,g=.0722,m=f()?ao.W§J:uJ.RgbQuantô'§N(JÃa4ò,Ü,eßó,a=bg,o=499,h=491,u=487,f=503,c=3*f,l=aæ,v=4,d=100,p=bh,xëp,g=ba,m=ba,b=x>>m,y=x<<g-m,w=a>>3,C=6,SëC,A=w*S,k=30,G=ba,IëG,D=8,PëD,U=G+D,jëU,EFLMO=n§4=B(tß,o¬h,uìiô,r=nÉo,e=ao(aÃh»hh¼)e[hµao(4Ãuí[h®uûµu[1µu[2µ(h<<v+8)/a,L[hµx/a,F[hµ0},z«³ti=ao(aÃr»rr¼)i[e[3]µr³s=0ß»nn¼¬oÊ[n]Ä]û®Ä]ÞÄ][2]}Øt},Hò,Ü߸ìh=0,u=0,t" +
                        "»tY(ní[t®rôÉnÞiô+1;iiÖoí[i®oÐ<s)rÊÉoÐoí[r®t!=r)i=oû®oûµnû®nûÌ1®o[1µnÞn[1Ì2®o[2µn[2®n[2Ì3®o[3µn[3®n[3µis!=ht+1;i<sth=s,uô}}l+1;i<bgl},N«V eÇl,p,x,g,m,b,y,w,S,G,Dr<c)s=1t=30+(sæ)/3,SÊ,G=0,D=r,w=r/(3*sÃy=0|w/d,m=I,x=A@=0ìe»e<g;e¼)M[eµm*(ù-e*e^r<cËr%o*oËr%h*hËr%u*u7 b=3*fìe»e<w;ºaÒ+0,lÒ+1,pÒ+2ß=T(a,l,pÃR(mÇl,pÃ0!=g)Q(gÇl,p)G+=b,G>=D)G-=re¼,0==y)y=10=í%yºm-=m/t,x-=x/k@=0ìn»n<g;n¼)M[nµm*(ù-n*n^}}}n§6¬s߸,f,cìu=1e3,c=æÉE[i®n=sæ;s<aÑn>»ºs<a)X(fí[s®o=fÐ-i,o>=u)s=a7{X(s¼¯o" +
                        "h=fÁtãºh=fÈrã)u=o,c=f[3]}}X(n>=0)X(fí[n®oÊ-fÞo>=u)n=æ7{X(n--¯oh=fÁtãºh=fÈrã)u=o,c=f[3]}}}Øc}ß.process«ØN(Ãq(ÃH(Ãz()}$qòìt»tt¼)e[t]û]Ót]ÐÓt][2]Ót][3µt},Q,s߬o,h,u,évuÊ-t,u<æ)u=æfÊ+t,f>a)f=aìoÊ+1,hÊæ,l=1;o<fÑh>u;ºc=M[l¼®o<fví[o¼]try{vû¡0]-rÍ1¡1]-sÍ2¡2]-n)/j}bf(d}}X(h>uví[h--]try{vû¡0]-rÍ1¡1]-sÍ2¡2]-n)/j}bf(d}}}},R,s߬aí×aÁô*(aÁr)/I,aÐ-ô*(aÐ-s)/I,aÈô*(aÈn)/I},T¬s߸,éd,xìl=~(1<<31Ãd=l,f=æ,c=f,s»ss¼ºxí[s®n=xÁtß<0)n=-no=xÐ-i¯on+=o,o=xÈr¯on+=oß<l)l=n,f=sh=n-(Få>>p-vÃh<d)d=h,c=su=Lå" +
                        ">>m,Lå-=u,Få+=u<<g}ØL[f]+=b,F[f]-=y,c}ØO§pply(J,argumentsÃn}0?134:¨¨¨???function¨this?return¨???var?prototype?if?for?hue?length¨else??case?idxrgb?Ut8Õ?idxi32?nearestIndex?palLocked?hue·i32idx?Ut32Õ?mHueColsðs?stats?num·dexOf?histogram?Õ?push?width?switch?toFixed?itColors?groupsFull?forEach?boxSize?break?255?method?i32rgb?i32i32?height?buffer?new?itDist?distIncr?buildPal?16711680?sort?palette?mCols?check?call?buf32?boxPxls?Math?nearestColorð2Dð1D?num?ject?null?getï?cols?4278190080?th" +
                        "old?sat·Pal?lum·65280?NeuQuant?sortPal?map?`?cñ?Object?10?throw?slice???catch?256?16",
                        "]-=c*(v[},t.W.a(t,i){(t,i,,J.aJ.a.a????????(B(i,r)=B(t){=B(){){V X(],,o<0)o=-,h<0)h=Y(V r=(t){KY(V =t§]=°-ho+=hGroups?,o,h,u&t)>>){X(=0;++J.Z)J.Z§)ax9 aE ab(£V r=[0]-}B ),t[s¼µe[oElement§s(2)),n,a,[2]-,s==i7 X(0!=µi,i=o[)/j,v[Imaget[o][1]||=(ay&S[G>>=v,e[aE ah(Array¼)X([i]K ئJ©{Øt(=aQ.max):2=Ê?i,r,s)9[1®,nar(h(t))Ùi,r)Ñs(aI¹bh¶,o<u bd [s]-1r§X(2d~~(t§m(f,c,l,/=ay,=1<<Y(=ear(¦z){Context?coloranvas«V t={}=t[ay&t,(ao»o<r;oString,e=s.(g*g§p([0®0!=(aZ&[2]?æ:n)/2.3)§v(B()b=3<a;){:¦kקY.h,t§fÃ:n=nÑ])<<v=B¤r[r]Y(E[hµu+>>1,i=hannot StatsÑba¥=[®in;i¼)E[iµ,g=x>>Creduceax9):aWV }),g<=1)g)*P/ù))sampleÅ:r=",
                        ""
                ]
            ]));
        </script>
    </body>
</html>
 
// The following tells Js Bin to not protect us from infinite loops...
// noprotect
// Dithering an image converted to 256 colours
//  I use RgbQuant to convert to 256 colours and then the following function to dither it.
// http://unitzeroone.com/blog/2008/05/06/opensource-image-dithering-for-as3-demosource/
// https://code.google.com/p/imageditheringas3/source/browse/trunk/ImageDitheringAS3/src/com/unitzeroone/fx/ImageDithering.as
Bitmap.prototype.dither = function(kernel, serpentine) {
    var kernels = {
        FalseFloydSteinberg: [
            [3 / 8, 1, 0],
            [3 / 8, 0, 1],
            [2 / 8, 1, 1]
        ],
        FloydSteinberg: [
            [7 / 16, 1, 0],
            [3 / 16, -1, 1],
            [5 / 16, 0, 1],
            [1 / 16, 1, 1]
        ],
        Stucki: [
            [8 / 42, 1, 0],
            [4 / 42, 2, 0],
            [2 / 42, -2, 1],
            [4 / 42, -1, 1],
            [8 / 42, 0, 1],
            [4 / 42, 1, 1],
            [2 / 42, 2, 1],
            [1 / 42, -2, 2],
            [2 / 42, -1, 2],
            [4 / 42, 0, 2],
            [2 / 42, 1, 2],
            [1 / 42, 2, 2]
        ],
        Atkinson: [
            [1 / 8, 1, 0],
            [1 / 8, 2, 0],
            [1 / 8, -1, 1],
            [1 / 8, 0, 1],
            [1 / 8, 1, 1],
            [1 / 8, 0, 2]
        ]
    }
    if (!kernel || !kernels[kernel]) return;
    var ds = kernels[kernel];
    var index = 0,
        height = this.height,
        width = this.width,
        data = this.data;
    var direction = serpentine ? -1 : 1;
    for (var y = 0; y < height; y++) {
        if (serpentine) direction = direction * -1;
            for (var x = direction==1?0:width-1, xend = direction==1?width:0; x != xend; x=x+direction){
            index = (y * width) + x;
            // Get original colour
            var idx = index * 4;
            var r1 = data[idx];
            var g1 = data[idx + 1];
            var b1 = data[idx + 2];
            // Get converted colour
            idx = this.findPaletteColor([r1, g1, b1]);
            this.indexedData[index] = idx;
            idx = idx * 3;
            var r2 = this.indexedPalette[idx];
            var g2 = this.indexedPalette[idx + 1];
            var b2 = this.indexedPalette[idx + 2];
            var er = r1 - r2;
            var eg = g1 - g2;
            var eb = b1 - b2;
                for (var i = direction==1?0:ds.length-1, end = direction==1?ds.length:0; i != end; i=i+direction) {
                var x1 = ds[i][1]; // *direction;  //  Should this by timesd by direction?..to make the kernel go in the opposite direction....got no idea....
                var y1 = ds[i][2];
                if (x1 + x >= 0 && x1 + x < width && y1 + y >= 0 && y1 + y < height) {
                    var d = ds[i][0];
                    idx = index + x1 + (y1 * width);
                    idx = idx * 4;
                    r1 = data[idx] + (er * d);
                    g1 = data[idx + 1] + (eg * d);
                    b1 = data[idx + 2] + (eb * d);
                    data[idx] = r1;
                    data[idx + 1] = g1;
                    data[idx + 2] = b1;
                }
            }
        }
    }
}
drawTest('#dither');
var t = Date.now();
dithered = Bitmap('#dither');
dithered.createIndexedData(true);
dithered.dither('FloydSteinberg', false);
ditheringstats.innerText = 'FloydSteinberg - ' + (Date.now() - t);
dithered.pixelWidth = 1;
dithered.putImageData();
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
PAEzpro
0viewers