JavaScript
Bu çözüm, görüntü verilerini çıkarmak için HTML5 canvas öğesini kullanır, ancak HTML kullanmanıza gerek kalmadan konsolunuzda çalıştırılabileceği anlamına gelir. Renk paleti görüntüsüne bir dizi olarak erişir; Palet görüntüsündeki tüm renkleri bir dizide sakladım). Konsola çıkış yapar (bittikten sonra) ve sonucu bir değişkende saklar.
Kodun en güncel sürümü kemanın içindedir . Keman ayrıca resimlerdeki gürültüyü azaltmak için daha iyi bir algoritma kullanır. Algoritmadaki gelişme çoğunlukla ters rengin seçilmesine neden olan bir fonksiyonun (maks. Min.) Sabitlenmesidir.
MS Paint Icon şeklinde kodlayın! (keman veya Yığın Parçacığında biçimlendirilmiş kod)
eval(` function
Paint(t){fun
ction n(t){va
r n=t.toString(
16);return 1==n.
length?"0"+n:n}fu
nction e(t){return
"#"+n(t[0])+n(t[1]
)+n(t[2])}var a=ne
w Image,i=document.
createElement("canv
as"),h=null,o=docum
ent.createElement(
"canvas"),r= o.getContext("2d
") ,l=[],u=this,c =[[0,0,0],[255
,2 55,255],[ 192,192, 192],[128,12
8 ,128],[126,3,8],[252,13,27] ,[255,25
3, 56],[128,127,23],[15,127,18],[ 41,253
, 46],[45,255,254],[17,128,127],[2 ,12,1
2 6],[ 11,36,2 51],[252,40,252],[12 7,15,1
2 6],[ 128,127 ,68],[255,253,136],[4 2,253,
1 33], [4,64,64],[23 ,131,251],[133,255,254],
[ 129 ,132,252],[6,6 6,126],[127,37,2 51],[127,
6 4,1 3],[253,128,73],[252,22,129]];a.crossOrigin
= "", a.src=t,this.done=this.done||function(){},a.o
n load=function(){function t(t){var n=0,e=0,a=0;return
t .forEach(function(t){n+=t[0],e+=t[1],a+=t[2]}),[n/t.leng
t h,e /t.length,a/t.length]}function n(t){for(var n=[],e=0;e
< t.l ength;e+=1)n.push(t[e]);return n}function g(t,n){retur
n (Ma th.abs(t[0]-n[0])/255+Math.abs(t[1]-n[1])/255+Math.abs(t
[ 2]- n[2])/255)/3}function f(t,n){for(var e=Math.floor(Math.ran
do m()*n.length),a=n[e],i=(g(t,a),1-.8),h=56,o=[];o.length<=h&
&g (t,a)>i;)if(o.push(a),a=n[Math.floor(Math.random()*n.length)]
, o.length==h){var r=o.map(function(n){return g(t,n)});a=o[r.indexO
f(Math.max.apply(Math,r))],o.push(a)}return a}function s(t,n){for(
v ar e=[];t.length>0;)e.push(t.splice(0,n).slice(0,-1));return e}i.w
i dth=a.width,i.height=2*a.height,h=i.getContext("2d"),h.drawImage(a,0
,0,a.width,a.height);for(var d=(function(t){reduce=t.map(function(t){re
turn(t[ 0]+t[1]+t[2])/3})}(c),0),m=0,v=i.width*i.height/4,p=0;v>p;p+=1)d
>2*Mat h.ceil(a.width/2)&&(d=0,m+=1),l.push(f(t(s(n(h.getImageData(2*d,2
*m,4,4).data),4)),c)),d+=1;o.width=i.width,o.height=i.height;for(var d=0
,m=0,v=i.width*i.height/4,p=0;v>p;p+=1)d>2*Math.ceil(a.width/2)&&(d=0,m+=
1),console.log("Filling point ("+d+", "+m+") : "+e(l[p])),r.fillStyle=e(l
[p]),r.fillRect(2*d+1,2*m,2,1) ,r.fillRect(2*d,2*m+1,4,2),r.fillRect(2*d
+1,2*m+3,2,1),d+=1;u.result=o .toDataURL("image/png"),u.resultCanvas
=o,u.imageCanvas=i,u.image=a ,u.done(),console.log(u.result)},a.one
rror=function(t){console.log ("The image failed to load. "+t)}}/*..
............................ ......................................
. .......................... .....................................
............................ ......................................
............................. .......................................
.......................................................................
.......................................................................
.................. ..................................................
................ .................................................
.............. ................................................
............. ................................................
........... .................................................
......... ................................................
....... ................................................
.... ................................................
................................................
...............................................
...............................................
..............................................
.............................................
............................................
..........................................
.......................................
.....................................
.................................
.............................
......................
.....
.....
.....
....
*/`
.replace(/\n/g,''))
Kullanımı:
Paint('DATA URI');
Keman, crossorigin.me'yi kullanır, böylece çapraz kaynak-kaynak paylaşımı konusunda endişelenmenize gerek yoktur.
Fiddle'ı da güncelledim, böylece en iyi görünen resmi üretmek için bazı değerleri ayarlayabilirsiniz. Bazı resimlerin renkleri kapalı olabilir, bundan kaçınmak için algoritmayı ayarlamak için accept_rate değerini ayarlayın. Daha düşük bir sayı daha iyi gradyanlar anlamına gelir, daha yüksek bir sayı daha net renklere neden olur.
İşte bir Stack-Snippet olarak keman (kemanın çalışmaması durumunda güncellenmez):
/* Options */
var accept_rate = 82, // 0 (low) - 100 (high)
attempts = 16, // Attemps before giving up
edge_multi = 2; // Contrast, 2-4
function Paint(image_url) {
var image = new Image(), canvas = document.createElement('canvas'), context = null, result = document.createElement('canvas'), resultContext = result.getContext('2d'), final_colors = [], self = this, color_choices = [
[0,0,0],
[255,255,255],
[192,192,192],
[128,128,128],
[126,3,8],
[252,13,27],
[255,253,56],
[128,127,23],
[15,127,18],
[41,253,46],
[45,255,254],
[17,128,127],
[2,12,126],
[11,36,251],
[252,40,252],
[127,15,126],
[128,127,68],
[255,253,136],
[42,253,133],
[4,64,64],
[23,131,251],
[133,255,254],
[129,132,252],
[6,66,126],
[127,37,251],
[127,64,13],
[253,128,73],
[252,22,129]
];
image.crossOrigin = "";
image.src = image_url;
this.done = this.done || function () {};
function hex(c) {
var res = c.toString(16);
return res.length == 1 ? "0" + res : res;
}
function colorHex(r) {
return '#' + hex(r[0]) + hex(r[1]) + hex(r[2]);
}
image.onload = function () {
canvas.width = image.width; canvas.height = image.height * 2;
context = canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
function averageColors(colors_ar) {
var av_r = 0,
av_g = 0,
av_b = 0;
colors_ar.forEach(function (color) {
av_r += color[0];
av_g += color[1];
av_b += color[2];
});
return [av_r / colors_ar.length,
av_g / colors_ar.length,
av_b / colors_ar.length];
}
function arrayFrom(ar) {
var newar = [];
for (var i = 0; i < ar.length; i += 1) {
newar.push(ar[i]);
}
return newar;
}
function colorDif(c1,c2) {
// Get's distance between two colors 0.0 - 1.0
return (Math.abs(c1[0] - c2[0]) / 255 +
Math.abs(c1[1] - c2[1]) / 255 +
Math.abs(c1[2] - c2[2]) / 255) / 3;
}
var furthest = (function (cc) {
// Determines furthest color
// Reduces RGB into a "single value"
reduce = cc.map(function(color) {
return ( color[0] + color [1] + color [2] ) / 3;
});
}(color_choices));
function intDif(i1,i2,t) {
return Math.abs(i1 - i2) / t
}
function arrayIs(ar, int,d) {
return intDif(ar[0],int,255) <= d &&
intDif(ar[1],int,255) <= d &&
intDif(ar[2],int,255) <= d
}
function colorLoop(c1,c2) {
var edgeCap = edge_multi * ((accept_rate / 100) / 50), values = c2.map(function (i) {
return colorDif(c1,i);
});
return arrayIs(c1,255,edgeCap)?[255,255,255]:
arrayIs(c1,0,edgeCap) ?[0,0,0]:
c2[values.indexOf(Math.min.apply(Math, values))];
}
function colorFilter(c1, c2) {
// Does the color stuff
var rand = Math.floor( Math.random() * c2.length ), // Random number
color = c2[rand], // Random color
randdif = colorDif(c1, color),
threshhold = 1 - accept_rate / 100, // If the color passes a threshhold
maxTries = attempts, // To avoid infinite looping, 56 is the maximum tries to reach the threshold
tries = [];
// Repeat until max iterations have been reached or color is close enough
while ( tries.length <= maxTries && colorDif( c1, color ) > threshhold ) {
tries.push(color);
color = c2[Math.floor(Math.random() * c2.length)]; // Tries again
if (tries.length == maxTries) {
// Used to hold color and location
var refLayer = tries.map(function(guess) {
return colorDif(c1, guess);
});
color = tries[refLayer.indexOf(Math.min.apply(Math, refLayer))];
tries.push(color);
}
}
var edgeCap = edge_multi * ((accept_rate / 100) / 50), loop = colorLoop(c1, c2);
return arrayIs(c1,255,edgeCap)?[255,255,255]:
arrayIs(c1,0,edgeCap) ?[0,0,0]:
colorDif(c1,color)<accept_rate?color:
loop;
}
function chunk(ar, len) {
var arrays = [];
while (ar.length > 0)
arrays.push(ar.splice(0, len).slice(0, -1));
return arrays;
}
var x = 0, y = 0, total = (canvas.width * canvas.height) / 4;
for (var i = 0; i < total; i += 1) {
if (x > (Math.ceil(image.width / 2) * 2)) {
x = 0;
y += 1;
}
final_colors.push( colorFilter( averageColors( chunk( arrayFrom(context.getImageData(x * 2, y * 2, 4, 4).data), 4 ) ), color_choices) );
x += 1;
}
// Paint Image
result.width = canvas.width;
result.height = canvas.height;
var x = 0, y = 0, total = (canvas.width * canvas.height) / 4;
for (var i = 0; i < total; i += 1) {
if (x > (Math.ceil(image.width / 2) * 2)) {
x = 0;
y += 1;
}
console.log("Filling point (" + x + ", " + y + ") : " + colorHex(final_colors[i]));
resultContext.fillStyle = colorHex(final_colors[i]);
resultContext.fillRect(x*2 + 1, y * 2, 2 , 1); // Top
resultContext.fillRect(x * 2, y * 2 + 1, 4, 2); // Middle
resultContext.fillRect(x * 2 + 1, y * 2 + 3, 2, 1); // Bottom
x += 1;
}
self.result = result.toDataURL("image/png");
self.resultCanvas = result;
self.imageCanvas = canvas;
self.image = image;
self.done();
console.log(self.result);
};
image.onerror = function(error) {
console.log("The image failed to load. " + error);
}
}
// Demo
document.getElementById('go').onclick = function () {
var url = document.getElementById('image').value;
if (!url.indexOf('data:') == 0) {
url = 'http://crossorigin.me/' + url;
}
var example = new Paint(url);
example.done = function () {
document.getElementById('result').src = example.result;
document.getElementById('result').width = example.resultCanvas.width;
document.getElementById('result').height = example.resultCanvas.height;
window.paint = example;
};
};
<!--This might take a while-->
Enter the image data URI or a URL, I've used crossorigin.me so it can perform CORS requests to the image. If you're inputting a URL, be sure to include the http(s)
<input id="image" placeholder="Image URI or URL"><button id="go">Go</button>
<hr/>
You can get the image URI from a website like <a href="http://jpillora.com/base64-encoder/">this one</a>
<hr/>
Result:
<img id="result">
<span id="error"></span><hr/>
Check your console for any errors. After a second, you should see the colors that are being generated / printed getting outputted to the console.
New Horizon'un Pluto bayrağını anmak için Pluto'nun bir görüntüsünü girdim:
Aşağıdakiler için orijinaline mümkün olduğunca yakın olmalarını sağlamak için ayarladım:
Bunu OS X Yosemite'nin varsayılan duvar kağıdına koştum. Bir süre çalıştırıldıktan sonra sonuçlar kesinlikle çok etkileyici. Orijinal dosya çok büyüktü (26 MB), böylece yeniden boyutlandırdım ve sıkıştırdım:
Yıldızlı gece (Daha iyi sonuçlar için daha yüksek çözünürlüklü bir görüntü kullandım )
Google'da bulduğum bir resim: