एमएस पेंट का संचालन किया जाता है


48

एमएस पेंट हमेशा एक महान समय का नुक़सान था, लेकिन यह अधिकांश ग्राफिक डिजाइनरों द्वारा चौंक गया था। शायद लोगों ने झकझोरने वाले रंग पैलेट के कारण, या सीमित पूर्ववत स्तरों के कारण रुचि खो दी। बावजूद, अभी भी मानक मानक ब्रश और डिफ़ॉल्ट रंग पैलेट के साथ सुंदर छवियां उत्पन्न करना संभव है।

चुनौती

केवल डिफ़ॉल्ट ब्रश (बिना कोनों वाला 4x4 वर्ग) और डिफ़ॉल्ट रंग पैलेट (नीचे 28 रंग) का उपयोग करके, स्टोचैस्टिक हिल क्लाइम्बिंग के आधार पर एक तकनीक का उपयोग करके स्रोत छवि को दोहराने का प्रयास किया जाता है ।

यहाँ छवि विवरण दर्ज करें

कलन विधि

हर उत्तर को एक ही मूल एल्गोरिथ्म (स्टोचस्टिक हिलक्लिंब) का पालन करना चाहिए। विवरण को प्रत्येक चरण के भीतर रखा जा सकता है। एक आंदोलन को ब्रश का एक स्ट्रोक माना जाता है (यानी पेंट में क्लिक करना)।

  1. अगले आंदोलन (अनुमानों) का अनुमान लगाएं। अगले आंदोलन के लिए एक अनुमान (निर्देशांक और रंगों का) बनाएं जो आप चाहें। हालाँकि अनुमान स्रोत छवि का संदर्भ नहीं होना चाहिए।
  2. अनुमान लागू करें। पेंटिंग को आंदोलन (रों) करने के लिए ब्रश पर लागू करें।
  3. आंदोलन के लाभ को मापें। स्रोत छवि को संदर्भित करके, यह निर्धारित करें कि क्या आंदोलन (एस) ने पेंटिंग को लाभान्वित किया (यानी पेंटिंग अधिक बारीकी से स्रोत छवि से मिलती जुलती है)। यदि यह फायदेमंद है, तो आंदोलन को रोकें, अन्यथा आंदोलन को रोकें।
  4. अभिसरण तक दोहराएँ। चरण 1 पर जाएं और अगले अनुमान की कोशिश करें जब तक कि एल्गोरिथ्म पर्याप्त रूप से परिवर्तित न हो जाए। पेंटिंग को इस बिंदु पर स्रोत की छवि से काफी मेल खाना चाहिए।

यदि आपका कार्यक्रम इन चार चरणों से मेल नहीं खाता है, तो यह संभवतः स्टोचस्टिक हिलक्लिम्ब नहीं है। मैंने इसे एक लोकप्रियता प्रतियोगिता के रूप में चिह्नित किया है क्योंकि लक्ष्य सीमित रंग पैलेट और ब्रश के आधार पर दिलचस्प पेंटिंग एल्गोरिदम का उत्पादन करना है।

contraints

  • एल्गोरिथ्म को किसी तरह से स्टोचस्टिक होना चाहिए ।
  • अगला अनुमान स्रोत छवि से प्रभावित नहीं होना चाहिए। आप प्रत्येक नए आंदोलन का अनुमान लगा रहे हैं, और फिर यह देखने के लिए जाँच कर रहे हैं कि यह मदद की है या नहीं। उदाहरण के लिए, आपको यह निर्धारित करने की अनुमति नहीं है कि स्रोत छवि के रंगों के आधार पर ब्रश को कहां रखा जाए (यह स्रोत छवि को धता बताने के समान है, जो लक्ष्य नहीं है)।

  • हालाँकि आपको जो एल्गोरिथम पसंद आएगा, उसके चरणों को संशोधित करके प्लेसमेंट को प्रभावित करने की अनुमति है। उदाहरण के लिए, आप किनारों पर अपने अनुमानों को शुरू कर सकते हैं और अंदर की ओर बढ़ सकते हैं, प्रत्येक अनुमान के लिए लाइनें बनाने के लिए ब्रश को खींचें या पहले गहरे रंगों को पेंट करने का निर्णय लें। आपको अगले वांछित आंदोलन की गणना करने के लिए पिछली पुनरावृत्ति छवियों (लेकिन स्रोत छवि नहीं) को संदर्भित करने की अनुमति है। ये प्रतिबंधात्मक हो सकते हैं, जैसा कि आप चाहते हैं (यानी केवल वर्तमान पुनरावृत्ति के लिए शीर्ष-बाएं चतुर्थांश के भीतर अनुमान लगाते हैं)।

  • स्रोत छवि और वर्तमान पुनरावृति के बीच "अंतर" के माप को तब तक मापा जा सकता है जब तक आप चाहें, जब तक यह निर्धारित करने के लिए अन्य संभावित आंदोलनों की गणना नहीं करता है कि क्या यह आंदोलन "सर्वश्रेष्ठ" माना जाता है। यह नहीं पता होना चाहिए कि क्या वर्तमान आंदोलन "सर्वश्रेष्ठ" है, केवल यह कि क्या यह मानदंड मानदंड को बर्दाश्त करने के भीतर है। उदाहरण के लिए, यह abs(src.R - current.R) + abs(src.G - current.G) + abs(src.B - current.B)प्रत्येक प्रभावित पिक्सेल, या किसी भी प्रसिद्ध रंग अंतर तकनीकों के रूप में सरल हो सकता है ।

पैलेट

आप पैलेट को एक 28x1 छवि के रूप में डाउनलोड कर सकते हैं या इसे सीधे कोड में बना सकते हैं।

ब्रश

ब्रश कोनों के बिना एक 4x4 वर्ग है। यह इसका एक छोटा संस्करण है:

यहाँ छवि विवरण दर्ज करें

(आपका कोड 4x4 संस्करण का उपयोग करना चाहिए)

उदाहरण

इनपुट:

वान गाग - द स्टार्री नाइट

आउटपुट:

तारों वाली रात उत्पन्न हुई

आप देख सकते हैं कि मेरे द्वारा किए गए एक छोटे वीडियो में बुनियादी एल्गोरिदम कैसे आगे बढ़ता है (प्रत्येक फ्रेम 500 पुनरावृत्तियों है): द स्टाररी नाइट । प्रारंभिक चरण देखने के लिए दिलचस्प हैं:

यहाँ छवि विवरण दर्ज करें


1
@ vihan1086: स्रोत की छवि में पारदर्शिता नहीं है। वर्तमान छवि पिछली पुनरावृत्ति पर निर्भर कर सकती है (जैसे कि मेरा उदाहरण, जिसमें पिछले के शीर्ष पर नए बिंदु जोड़े जाते हैं) यदि आपका मतलब है।
ग्रूव्सएनएल

मैं यह नहीं देखता कि स्टोकेस्टिक हिल क्लाइम्बिंग क्या कहती है ... यह देखते हुए कि आप अनुमान लगा सकते हैं लेकिन आप चाहते हैं और उन्हें छोड़ दें यदि वे अच्छे नहीं हैं, तो यह प्रभावी रूप से वही है जो चेकिंग के दौरान अनुमानों के एक समूह से गुजर रहा है और सबसे अच्छा एक उठा।
Sp3000

@ Sp3000: बिंदु यह है कि आप "सर्वश्रेष्ठ" आंदोलन को तब तक नहीं जानते हैं जब तक कि यह एक संभावित आंदोलन नहीं बन गया है, जिस बिंदु पर आप इसे स्वीकार करना चुन सकते हैं यदि यह आपके स्वयं के स्वीकृति मानदंडों के अंदर फिट बैठता है। ")। स्वीकृति मानदंड में सभी संभावित चालों का ज्ञान नहीं होना चाहिए (मुझे इसे और स्पष्ट करने की आवश्यकता हो सकती है)। अनिवार्य रूप से आपको समय से पहले "सर्वश्रेष्ठ" आंदोलन निर्धारित करने में सक्षम नहीं होना चाहिए, इसके बजाय आपको छवि में सुधार करना चाहिए।
ग्रूव्सएनएल

इस ब्रश के आकार के साथ, क्या कोने के पिक्सल को चित्रित करना असंभव है (आपके उदाहरण से मुझे यह आभास मिलता है), या क्या ब्रश को छवि सीमाओं के बाहर आंशिक रूप से रखा जा सकता है?
ओलिपहंट

Sp3000 की चिंता में संभवतः निम्नलिखित निर्धारक एल्गोरिथम शामिल हैं: बदले में प्रत्येक पिक्सेल के लिए, हर रंग का प्रयास करें। कोई स्थिरता नहीं है और बहुत कुछ पसंद है, फिर भी यह नियमों के अनुकूल है।
ओलिपफंट

जवाबों:


35

जावास्क्रिप्ट

यह समाधान छवि डेटा को निकालने के लिए HTML5 कैनवास तत्व का उपयोग करता है, लेकिन HTML का उपयोग करने की आवश्यकता के बिना, इसका मतलब है कि यह आपके कंसोल में चलाया जा सकता है। यह एक सरणी के रूप में रंग पैलेट छवि का उपयोग करता है; मैंने सभी रंगों को एक सरणी में पैलेट छवि से संग्रहीत किया है)। यह कंसोल के लिए आउटपुट (इसके खत्म होने के बाद) और परिणाम को एक चर में संग्रहीत करता है।

कोड का सबसे अपडेटेड वर्जन फिडेल में है । फ़िडेल चित्रों में शोर को कम करने के लिए एक बेहतर एल्गोरिथ्म का भी उपयोग करता है। एल्गोरिथ्म में सुधार ज्यादातर एक फ़ंक्शन (अधिकतम से न्यूनतम) तय कर रहा है जिसके कारण उलटा रंग चुना गया था।

एमएस पेंट आइकन के आकार में कोड! (फेटल या स्टैक स्निपेट में स्वरूपित कोड)

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,''))                                             

उपयोग:

Paint('DATA URI');

फील करना

फिडेल crossorigin.me का उपयोग करता है, इसलिए आपको क्रॉस-ऑरिजिन-रिसोर्स-शेयरिंग के बारे में चिंता करने की आवश्यकता नहीं है।

मैंने फ़िडेल को भी अपडेट किया है ताकि आप सबसे अच्छी दिखने वाली पेंटिंग का निर्माण करने के लिए कुछ मूल्यों को समायोजित कर सकें। कुछ चित्रों के रंग बंद हो सकते हैं, इससे बचने के लिए, एल्गोरिथ्म को समायोजित करने के लिए accept_rate को समायोजित करें। कम संख्या का अर्थ है बेहतर ग्रेडिएंट, अधिक संख्या में तेज रंगों का परिणाम होगा।


यहाँ स्टैड-स्निपेट के रूप में फिडेल है (यदि फ़िडल काम नहीं करता है तो अद्यतन नहीं किया जाता है):


प्लूटो के न्यू होराइजन के फ्लाईबाई को मनाने के लिए, मैंने प्लूटो की एक छवि डाली है:

मूल तैयार

मूल तैयार

निम्नलिखित के लिए मैंने इसे मूल रूप से जितना संभव हो उतना करीब से बना दिया है:

मैंने इसे OS X Yosemite के डिफ़ॉल्ट वॉलपेपर के साथ चलाया। इसे थोड़ा चलाने के लिए छोड़ने के बाद, परिणाम बिल्कुल आश्चर्यजनक हैं। मूल फ़ाइल बहुत बड़ी (26 MB) थी, इसलिए मैंने उसका आकार बदला और उसे संकुचित कर दिया:

यहाँ छवि विवरण दर्ज करें

तारों वाली रात (मैंने बेहतर परिणामों के लिए उच्च रिज़ॉल्यूशन की छवि का उपयोग किया है )

एक तस्वीर जो मुझे गूगल पर मिली: यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें


12

जावास्क्रिप्ट + एचटीएमएल

रैंडम:

रैंडम प्वाइंट

यादृच्छिक संरेखित:

कैनवास को 4x4 वर्गों में विभाजित करता है, और एक वर्ग के अंदर एक बिंदु को यादृच्छिक रूप से चुनता है। ऑफ़सेट ग्रिड को स्थानांतरित करेंगे, जिससे आप थोड़ा अंतराल भर सकते हैं।

लूप:

सभी बिंदुओं के माध्यम से एक ग्रिड और लूप बनाता है। ऑफसेट ग्रिड को स्थानांतरित करता है। रिक्ति प्रत्येक कोशिका के आकार का निर्धारण करती है। (वे ओवरलैप करना शुरू कर देंगे)

रंग में अंतर:

  • आरजीबी
  • एचएसएल
  • एचएसवी

var draw = document.getElementById("canvas").getContext("2d");
var data = document.getElementById("data").getContext("2d");
colors = [
    [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]
];
iteration = 0;
fails = 0;
success = 0;
x = 0;
y = 0;
//Init when the Go! button is pressed
document.getElementById("file").onchange = function (event) {
    document.getElementById("img").src = URL.createObjectURL(event.target.files[0]);
    filename = document.getElementById("file").value;
    /*if (getCookie("orginal") == filename) {
        console.log("Loading from Cookie");
        reload = true;
        document.getElementById("reload").src = getCookie("picture");
    }*/
};

/*function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1);
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
    }
    return "";
}*/

//Run when the image has been loaded into memory
document.getElementById("img").onload = function () {
    document.getElementById("file").disable = "true";
    document.getElementById("canvas").hidden = "";
    document.getElementById("canvas").height = document.getElementById("img").height;
    document.getElementById("data").height = document.getElementById("img").height;
    document.getElementById("canvas").width = document.getElementById("img").width;
    document.getElementById("data").width = document.getElementById("img").width;

    var imgData = draw.createImageData(document.getElementById("img").width, document.getElementById("img").height);
    for (var i = 0; i < imgData.data.length; i += 4) {
        imgData.data[i + 0] = 0;
        imgData.data[i + 1] = 0;
        imgData.data[i + 2] = 0;
        imgData.data[i + 3] = 255;
    }
    draw.putImageData(imgData, 0, 0);
    data.putImageData(imgData, 0, 0);
    if (reload == true) {
        draw.drawImage(document.getElementById("reload"), 0, 0);
    }
    data.drawImage(document.getElementById("img"), 0, 0);
    setInterval(function () {
        for (var u = 0; u < document.getElementById("selectColor").value; u++) {
            doThing();
        }
    }, 0);
};

//The core function. Every time this function is called, is checks/adds a dot.
function doThing() {
    getCoords();
    paintBucket();
    console.count("Iteration");
    if (compare(x, y)) {
        draw.putImageData(imgData, x, y);
    }
}

function getCoords() {
    switch (document.getElementById("selectCord").value) {
        case "1":
            x = Math.floor(Math.random() * (document.getElementById("img").width + 4));
            y = Math.floor(Math.random() * (document.getElementById("img").height + 4));
            break;
        case "2":
            x = Math.floor(Math.random() * ((document.getElementById("img").width + 4) / 4)) * 4;
            console.log(x);
            x += parseInt(document.getElementById("allignX").value);
            console.log(x);
            y = Math.floor(Math.random() * ((document.getElementById("img").height + 4) / 4)) * 4;
            y += parseInt(document.getElementById("allignY").value);
            break;
        case "3":
            x += parseInt(document.getElementById("loopX").value);
            if (x > document.getElementById("img").width + 5) {
                x = parseInt(document.getElementById("allignX").value);
                y += parseInt(document.getElementById("loopY").value);
            }
            if (y > document.getElementById("img").height + 5) {
                y = parseInt(document.getElementById("allignY").value);
            }
    }
}

function compare(arg1, arg2) {
    var arg3 = arg1 + 4;
    var arg4 = arg2 + 4;
    imgData2 = data.getImageData(arg1, arg2, 4, 4);
    imgData3 = draw.getImageData(arg1, arg2, 4, 4);
    N = 0;
    O = 0;
    i = 4;
    addCompare();
    addCompare();
    i += 4;
    for (l = 0; l < 8; l++) {
        addCompare();
    }
    i += 4;
    addCompare();
    addCompare();
    i += 4;
    //console.log("New Score: " + N + " Old Score: " + O);
    iteration++;
    /*if(iteration>=1000){
        document.cookie="orginal="+filename;
        document.cookie="picture length="+document.getElementById("canvas").toDataURL().length;
        document.cookie="picture="+document.getElementById("canvas").toDataURL();
        
    }*/
    if (N < O) {
        return true;
    } else {
        return false;
    }
}

function addCompare() {
    if (document.getElementById("colorDif").value == "HSL") {
        HSLCompare();
        i += 4;
        return;
    }
    if (document.getElementById("colorDif").value == "HSV") {
        HSVCompare();
        i += 4;
        return;
    }
    N += Math.abs(imgData.data[i] - imgData2.data[i]);
    N += Math.abs(imgData.data[i + 1] - imgData2.data[i + 1]);
    N += Math.abs(imgData.data[i + 2] - imgData2.data[i + 2]);
    O += Math.abs(imgData3.data[i] - imgData2.data[i]);
    O += Math.abs(imgData3.data[i + 1] - imgData2.data[i + 1]);
    O += Math.abs(imgData3.data[i + 2] - imgData2.data[i + 2]);
    i += 4;
}

function HSVCompare() {
    var NewHue = rgbToHsv(imgData.data[i], imgData.data[i + 1], imgData.data[i + 2])[0];
    var PicHue = rgbToHsv(imgData2.data[i], imgData2.data[i + 1], imgData2.data[i + 2])[0];
    var OldHue = rgbToHsv(imgData3.data[i], imgData3.data[i + 1], imgData3.data[i + 2])[0];

    var NScore = [Math.abs(NewHue - PicHue), ((NewHue < PicHue) ? NewHue + (1 - PicHue) : PicHue + (1 - NewHue))];
    var OScore = [Math.abs(OldHue - PicHue), ((OldHue < PicHue) ? OldHue + (1 - PicHue) : PicHue + (1 - OldHue))];
    
    
    NScore = Math.min(NScore[0], NScore[1]);
    OScore = Math.min(OScore[0], OScore[1]);
    
    NewHue = rgbToHsv(imgData.data[i], imgData.data[i + 1], imgData.data[i + 2])[1];
    PicHue = rgbToHsv(imgData2.data[i], imgData2.data[i + 1], imgData2.data[i + 2])[1];
    OldHue = rgbToHsv(imgData3.data[i], imgData3.data[i + 1], imgData3.data[i + 2])[1];
    
    NScore += Math.abs(NewHue-PicHue);
    OScore += Math.abs(OldHue-PicHue);
    
    NewHue = rgbToHsv(imgData.data[i], imgData.data[i + 1], imgData.data[i + 2])[2];
    PicHue = rgbToHsv(imgData2.data[i], imgData2.data[i + 1], imgData2.data[i + 2])[2];
    OldHue = rgbToHsv(imgData3.data[i], imgData3.data[i + 1], imgData3.data[i + 2])[2];
    
    N += Math.abs(NewHue-PicHue) + NScore;
    O += Math.abs(OldHue-PicHue) + OScore;
}

function rgbToHsv(r, g, b){
    r = r/255, g = g/255, b = b/255;
    var max = Math.max(r, g, b), min = Math.min(r, g, b);
    var h, s, v = max;

    var d = max - min;
    s = max == 0 ? 0 : d / max;

    if(max == min){
        h = 0; // achromatic
    }else{
        switch(max){
            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
            case g: h = (b - r) / d + 2; break;
            case b: h = (r - g) / d + 4; break;
        }
        h /= 6;
    }

    return [h, s, v];
}

function HSLCompare() {
    var result = 0;
    rgb = false;

    var NewHue = rgbToHue(imgData.data[i], imgData.data[i + 1], imgData.data[i + 2])[0];
    var PicHue = rgbToHue(imgData2.data[i], imgData2.data[i + 1], imgData2.data[i + 2])[0];
    var OldHue = rgbToHue(imgData3.data[i], imgData3.data[i + 1], imgData3.data[i + 2])[0];
    if (rgb == true) {
        N += Math.abs(imgData.data[i] - imgData2.data[i]);
        N += Math.abs(imgData.data[i + 1] - imgData2.data[i + 1]);
        N += Math.abs(imgData.data[i + 2] - imgData2.data[i + 2]);
        O += Math.abs(imgData3.data[i] - imgData2.data[i]);
        O += Math.abs(imgData3.data[i + 1] - imgData2.data[i + 1]);
        O += Math.abs(imgData3.data[i + 2] - imgData2.data[i + 2]);
        return;
    }
    var NScore = [Math.abs(NewHue - PicHue), ((NewHue < PicHue) ? NewHue + (1 - PicHue) : PicHue + (1 - NewHue))];
    var OScore = [Math.abs(OldHue - PicHue), ((OldHue < PicHue) ? OldHue + (1 - PicHue) : PicHue + (1 - OldHue))];
    
    
    NScore = Math.min(NScore[0], NScore[1]);
    OScore = Math.min(OScore[0], OScore[1]);
    
    NewHue = rgbToHue(imgData.data[i], imgData.data[i + 1], imgData.data[i + 2])[1];
    PicHue = rgbToHue(imgData2.data[i], imgData2.data[i + 1], imgData2.data[i + 2])[1];
    OldHue = rgbToHue(imgData3.data[i], imgData3.data[i + 1], imgData3.data[i + 2])[1];
    
    NScore += Math.abs(NewHue-PicHue);
    OScore += Math.abs(OldHue-PicHue);
    
    NewHue = rgbToHue(imgData.data[i], imgData.data[i + 1], imgData.data[i + 2])[2];
    PicHue = rgbToHue(imgData2.data[i], imgData2.data[i + 1], imgData2.data[i + 2])[2];
    OldHue = rgbToHue(imgData3.data[i], imgData3.data[i + 1], imgData3.data[i + 2])[2];
    
    N += Math.abs(NewHue-PicHue) + NScore;
    O += Math.abs(OldHue-PicHue) + OScore;
}

function rgbToHue(r, g, b) {
    if (Math.max(r, g, b) - Math.min(r, g, b) < 50) {
        rgb = true
    }
    r /= 255, g /= 255, b /= 255;
    var max = Math.max(r, g, b),
        min = Math.min(r, g, b);
    var h, s, l = (max + min) / 2;

    if (max == min) {
        h = s = 0; // achromatic
    } else {
        var d = max - min;
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
        switch (max) {
            case r:
                h = (g - b) / d + (g < b ? 6 : 0);
                break;
            case g:
                h = (b - r) / d + 2;
                break;
            case b:
                h = (r - g) / d + 4;
                break;
        }
        h /= 6;
    }
    return [h,s,l];
}

//Create a 4x4 ImageData object, random color selected from the colors var, transparent corners.
function paintBucket() {
    color = Math.floor(Math.random() * 28);
    imgData = draw.createImageData(4, 4);
    imgData2 = draw.getImageData(x, y, 4, 4);
    i = 0;
    createCorn();
    createColor();
    createColor();
    createCorn();
    for (l = 0; l < 8; l++) {
        createColor();
    }
    createCorn();
    createColor();
    createColor();
    createCorn();
}

function createCorn() {
    imgData.data[i] = imgData2.data[i];
    imgData.data[i + 1] = imgData2.data[i + 1];
    imgData.data[i + 2] = imgData2.data[i + 2];
    imgData.data[i + 3] = 255;
    i += 4;
}

function createColor() {
    imgData.data[i] = colors[color][0];
    imgData.data[i + 1] = colors[color][1];
    imgData.data[i + 2] = colors[color][2];
    imgData.data[i + 3] = 255;
    i += 4;
}
<canvas id="canvas" hidden></canvas>
<br>
<canvas id="data" hidden></canvas>
<br>
<input type="file" id="file"></input>
<br>
<img id="img">
<img id="reload" hidden>
<p>Algorithms:</p>
<select id="selectCord">
    <option value="1">Random</option>
    <option value="2">Random Alligned</option>
    <option value="3" selected>Loop</option>
</select>
<select id="selectColor">
    <option value="2000">Super Speedy</option>
    <option value="1000">Very Speedy</option>
    <option value="500" selected>Speedy</option>
    <option value="1">Visual</option>
</select>
<select id="colorDif">
    <option value="RGB" selected>RGB</option>
    <option value="HSL">HSL</option>
    <option value="HSV">HSV</option>
</select>
<p>Algorithm Options:
    <br>
</p>
<p>X Offset:
    <input id="allignX" type="range" min="0" max="3" value="0"></input>
</p>
<p>Y Offset:
    <input id="allignY" type="range" min="0" max="3" value="0"></input>
</p>
<p>Spacing X:
    <input id="loopX" type="range" min="1" max="4" value="2"></input>
</p>
<p>Spacing Y:
    <input id="loopY" type="range" min="1" max="4" value="2"></input>
</p>

यहाँ छवि विवरण दर्ज करें
RGB: यहाँ छवि विवरण दर्ज करें
HSL: यहाँ छवि विवरण दर्ज करें
HSV: यहाँ छवि विवरण दर्ज करें


बहुत ही शांत। "रन कोड स्निपेट" मेरे लिए तब टूटता है जब यह सेट करने की कोशिश करता है document.cookie(1000 पुनरावृत्तियों के बाद) क्योंकि दस्तावेज़ सैंडबॉक्स है। क्या कुकी आवश्यक है?
ग्रूव्सएनएल

नहीं, एक बार मैंने कुछ घंटों के लिए कार्यक्रम चलाया, लेकिन फिर मेरा ब्राउज़र क्रैश हो गया। इसलिए मैंने कुकी को एक बैकअप चीज़ के रूप में पकाया। लेकिन मैं इसे हटा दूँगा क्योंकि ऐसा लगता है कि स्टैक एक्सचेंज कुकीज़ को नापसंद करता है।
ग्रांट डेविस

1
आपके कोड को देखते हुए, मुझे लगता है कि यह उसी गति से लाभान्वित हो सकता है जो मैंने भेड़ियाहामर के उत्तर पर सुझाया था , इसके doThingबजाय लागू किया गया था loop। आपको अतिरिक्त लाइन के लायक गति में वृद्धि हो सकती है ...
ट्राइकोप्लाक्स

1
@trichoplax थैंक्यू अलॉट, न केवल आपके फिक्स ने मेरे प्रोग्राम की गति को बढ़ाया, जबकि फिक्सिंग मैंने पाया और एक गणित त्रुटि को ठीक किया, और मेरा प्रोग्राम अब उन छोटे काले डॉट्स को उत्पन्न नहीं करता।
ग्रन्थ डेविस

एक दम बढ़िया! नई आउटपुट इमेज ज्यादा बेहतर दिखती है।
ट्राइकोप्लाक्स

8

C # (संदर्भ कार्यान्वयन)

यह प्रश्न में छवियों को उत्पन्न करने के लिए उपयोग किया जाने वाला कोड है। मैंने सोचा कि कुछ लोगों को उनके एल्गोरिथ्म के आयोजन के लिए एक संदर्भ देना उपयोगी होगा। एक पूरी तरह से यादृच्छिक समन्वय और रंग प्रत्येक आंदोलन को चुना जाता है। यह ब्रश के आकार / स्वीकृति मानदंड द्वारा लगाई गई सीमाओं को देखते हुए आश्चर्यजनक रूप से अच्छा प्रदर्शन करता है।

मैं खुले स्रोत पुस्तकालय ColorMine से रंग अंतर को मापने के लिए CIEDE2000 एल्गोरिथ्म का उपयोग करता हूं । यह करीब रंग मैच (एक मानवीय दृष्टिकोण से) देना चाहिए, लेकिन इस पैलेट के साथ उपयोग किए जाने पर यह ध्यान देने योग्य अंतर नहीं लगता है।

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using ColorMine.ColorSpaces;
using ColorMine.ColorSpaces.Comparisons;

namespace Painter
{
    public class Painter
    {
        private readonly Bitmap _source;
        private readonly Bitmap _painting;
        private readonly int _width;
        private readonly int _height;
        private readonly CieDe2000Comparison _comparison = new CieDe2000Comparison();
        private const int BRUSHSIZE = 4;
        private readonly Random _random = new Random();
        private readonly ColorPalette _palette;

        private static readonly int[][] BRUSH = {
            new[] {1, 0}, new[] {2, 0},
            new[] {0, 1}, new[] {1, 1}, new[] {2, 1}, new[] {3, 1}, 
            new[] {0, 2}, new[] {1, 2}, new[] {2, 2}, new[] {3, 2}, 
            new[] {1, 3}, new[] {2, 3}
        };

        public Painter(string sourceFilename, string paletteFilename)
        {
            _source = (Bitmap)Image.FromFile(sourceFilename);
            _width = _source.Width;
            _height = _source.Height;

            _palette = Image.FromFile(paletteFilename).Palette;
            _painting = new Bitmap(_width, _height, PixelFormat.Format8bppIndexed) {Palette = _palette};

            // search for black in the color palette
            for (int i = 0; i < _painting.Palette.Entries.Length; i++)
            {
                Color color = _painting.Palette.Entries[i];
                if (color.R != 0 || color.G != 0 || color.B != 0) continue;
                SetBackground((byte)i);
            }
        }

        public void Paint()
        {
            // pick a color from the palette
            int brushIndex = _random.Next(0, _palette.Entries.Length);
            Color brushColor = _palette.Entries[brushIndex];

            // choose coordinate
            int x = _random.Next(0, _width - BRUSHSIZE + 1);
            int y = _random.Next(0, _height - BRUSHSIZE + 1);

            // determine whether to accept/reject brush
            if (GetBrushAcceptance(brushColor, x, y))
            {
                BitmapData data = _painting.LockBits(new Rectangle(0, y, _width, BRUSHSIZE), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
                byte[] bytes = new byte[data.Height * data.Stride];
                Marshal.Copy(data.Scan0, bytes, 0, bytes.Length);

                // apply 4x4 brush without corners
                foreach (int[] offset in BRUSH)
                {
                    bytes[offset[1] * data.Stride + offset[0] + x] = (byte)brushIndex;
                }
                Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
                _painting.UnlockBits(data);
            }
        }

        public void Save(string filename)
        {
            _painting.Save(filename, ImageFormat.Png);
        }

        private void SetBackground(byte index)
        {
            BitmapData data = _painting.LockBits(new Rectangle(0, 0, _width, _height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
            byte[] bytes = new byte[data.Height * data.Stride];
            for (int i = 0; i < data.Height; i++)
            {
                for (int j = 0; j < data.Stride; j++)
                {
                    bytes[i*data.Stride + j] = index;
                }
            }
            Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
            _painting.UnlockBits(data);
        }

        private bool GetBrushAcceptance(Color brushColor, int x, int y)
        {
            double currentDifference = 0.0;
            double brushDifference = 0.0;
            foreach (int[] offset in BRUSH)
            {
                Color sourceColor = _source.GetPixel(x + offset[0], y + offset[1]);
                Rgb sourceRgb = new Rgb {R = sourceColor.R, G = sourceColor.G, B = sourceColor.B};
                Color currentColor = _painting.GetPixel(x + offset[0], y + offset[1]);

                currentDifference += sourceRgb.Compare(new Rgb {R = currentColor.R, G = currentColor.G, B = currentColor.B}, _comparison);
                brushDifference += sourceRgb.Compare(new Rgb {R = brushColor.R, G = brushColor.G, B = brushColor.B}, _comparison);
            }
            return brushDifference < currentDifference;
        }
    }
}

फिर आप नीचे दिए गए कोड के समान एक उदाहरण (उदाहरण के लिए पुनरावृत्तियों / फ्रेम / नाम की संख्या के आधार पर) को कॉल करके छवियों की श्रृंखला (मेरे वीडियो की तरह) उत्पन्न कर सकते हैं। पहला तर्क स्रोत छवि के लिए फ़ाइल पथ है, दूसरा तर्क पैलेट (प्रश्न में जुड़ा हुआ) के लिए फ़ाइल पथ है, और तीसरा तर्क आउटपुट छवियों के लिए फ़ाइल पथ है।

namespace Painter
{
    class Program
    {
        private static void Main(string[] args)
        {
            int i = 0;
            int counter = 1;
            Painter painter = new Painter(args[0], args[1]);
            while (true)
            {
                painter.Paint();
                if (i%500000 == 0)
                {
                    counter++;
                    painter.Save(string.Format("{0}{1:D7}.png", args[2], counter));
                }
                i++;
            }
        }
    }
}

मैंने ऑनलाइन कुछ रंगीन कैनवास चित्रों की खोज की और नीचे की छवियों के पार आया, जो कि शानदार (जटिल) परीक्षण छवियां प्रतीत होती हैं। समस्त कॉपीराइट उनके संबंधित स्वामियों की संपत्ति हैं।

यहाँ छवि विवरण दर्ज करेंयहाँ छवि विवरण दर्ज करें स्रोत

यहाँ छवि विवरण दर्ज करेंयहाँ छवि विवरण दर्ज करें

स्रोत

यहाँ छवि विवरण दर्ज करेंयहाँ छवि विवरण दर्ज करें

स्रोत


यह है कि मुझे पता है कि मैं किसी भी चीज़ के बारे में कुछ नहीं जानता। अच्छा समाधान
ब्रैंडन

6

जावास्क्रिप्ट कैनवस

अपडेट करें

टिप्पणियों में उत्कृष्ट सुझाव। यह अब तेज़ है और ui को धीमा नहीं करता है!

function previewFile() {
  var srcImage = document.getElementById('srcImage');
  var file = document.querySelector('input[type=file]').files[0];
  var reader = new FileReader();

  reader.onloadend = function() {
    srcImage.src = reader.result;
  }

  if (file) {
    reader.readAsDataURL(file);
  } else {
    srcImage.src = "";
  }
}

var buckets = []; // buckets / iterations
var iter_per_focus = 5000;

var pal = "00FFFF,0000FF,00FF00,FFFF00,\
C0C0C0,FF0000,FF00FF,FFFF78,\
FF0078,FF7848,7878FF,78FFFF,\
00FF78,784800,007800,\
007878,787800,780000,787878,\
000078,780078,004878,7800FF,\
0078FF,004848,787848,000000,FFFFFF".split(",");
var pLen = pal.length;
var p = 0;
var _R = 0;
var _G = 1;
var _B = 2;
var _CAN = 3;

// Create fast access palette with r,g,b values and
// brush image for color.
function initPal() {

  for (var i = 0; i < pal.length; i++) {
    var r = parseInt(pal[i].substr(0, 2), 16);
    var g = parseInt(pal[i].substr(2, 2), 16);
    var b = parseInt(pal[i].substr(4, 2), 16);
    var pcan = document.createElement('canvas');
    pcan.width = 4;
    pcan.height = 4;
    var pctx = pcan.getContext('2d');
    pctx.fillStyle = '#' + pal[i];
    pctx.beginPath();
    pctx.rect(1, 0, 2, 4);
    pctx.rect(0, 1, 4, 2);
    pctx.fill();

    pal[i] = [r,g,b,pcan];

  }
}
initPal();

var score = [];
var can = document.getElementById("canB");
var ctx = can.getContext('2d');
var mainDiv = document.getElementById("main");
var bCan = document.createElement('canvas');
bCan.width = can.width;
bCan.height = can.height;
var bCtx = bCan.getContext('2d');

var canA = document.getElementById("canA");
can.width = can.height = canA.width = canA.height = 200;
var ctxA = canA.getContext('2d');
var imageData;
var data;

function getSrcImage() {
  var img = document.getElementById('srcImage');
  can.width = canA.width = img.width;
  can.height = canA.height = img.height;
  ctxA.drawImage(img, 0, 0);
  imageData = ctxA.getImageData(0, 0, img.width, img.height);
  data = imageData.data;
  
  // adjust for brush offset
  var w = can.width - 2;
  var h = can.height - 2;
  
  var n = Math.floor((w * h) / iter_per_focus);
  buckets = [];
  for (var i = 0; i < n; i++) {
    var bucket = [];
    bucket.r = Math.floor(Math.random() * pLen);
    buckets.push(bucket);
  }
  var b = 0;
  var pt = 0;
  for (var y = 0; y < h; y++) {
    for (var x = 0; x < w; x++, pt+=4) {
      var r = Math.floor((Math.random() * n));
      buckets[r].push([x,y,pt,256 * 12,Math.floor(Math.random()*pLen)]);
      b %= n;
    }
    pt += 8; // move past brush offset.
  }
    
}

var loopTimeout = null;

function loopInit() {
  var r, y, x, pt, c, s;
  var row = can.width * 4;
  
  var b = 0;

  function loop() {
    clearTimeout(loopTimeout);
    var bucket = buckets[b++];
    var len = bucket.length;
    // Stepping color
    //c = pal[p];
    // Pulsing color;
    //c = pal[Math.floor(Math.random()*pLen)]
    // Pulsting step
    c = pal[bucket.r++];
    bucket.r%=pLen;
    b %= buckets.length;
    if (b === 0) {
      p++;
      p%=pLen;
    }
    
    for (var i = 0; i < len; i++) {

      var x = bucket[i][0]
      var y = bucket[i][1];
      var pt = bucket[i][2];
      // Random color
      //c = pal[bucket[i][4]++];
      //bucket[i][4]%=pLen;
      
     
      s = Math.abs(data[pt] - c[_R]) +
        Math.abs(data[pt + 1] - c[_G]) +
        Math.abs(data[pt + 2] - c[_B]) +
        Math.abs(data[pt + 4] - c[_R]) +
        Math.abs(data[pt + 5] - c[_G]) +
        Math.abs(data[pt + 6] - c[_B]) +
        Math.abs(data[pt + row] - c[_R]) +
        Math.abs(data[pt + row + 1] - c[_G]) +
        Math.abs(data[pt + row + 2] - c[_B]) +
        Math.abs(data[pt + row + 4] - c[_R]) +
        Math.abs(data[pt + row + 5] - c[_G]) +
        Math.abs(data[pt + row + 6] - c[_B]);
      if (bucket[i][3] > s) {
        bucket[i][3] = s;
        bCtx.drawImage(c[_CAN], x - 1, y - 1);
      }

    }
    loopTimeout = setTimeout(loop, 0);
  }

  loop();
}

// Draw function is separate from rendering. We render
// to a backing canvas first.
function draw() {
  ctx.drawImage(bCan, 0, 0);
  setTimeout(draw, 100);
}

function start() {

  getSrcImage();
  imageData = ctxA.getImageData(0, 0, can.width, can.height);
  data = imageData.data;
  bCan.width = can.width;
  bCan.height = can.height;
  bCtx.fillStyle = "black";
  bCtx.fillRect(0, 0, can.width, can.height);
  loopInit();

  draw();
}
body {
  background-color: #444444;
  color: #DDDDEE;
}
#srcImage {
  display: none;
}
#testBtn {
  display: none;
}
#canA {
  display:none;
}
<input type="file" onchange="previewFile()">
<br>
<img src="" height="200" alt="Upload Image for MS Painting">

<button onclick="genImage()" id="testBtn">Generate Image</button>

<div id="main">
  <img id="srcImage" src="" onload="start()">
  <canvas id="canA"></canvas>
  <canvas id="canB"></canvas>
</div>


@trichoplax मैं छवि लोड करने के साथ कुछ क्रॉस साइट समस्याएँ थी। मैं देखूंगा कि क्या मैं कुछ समझ सकता हूं।
वोल्फहैमर

1
@trichoplax कोई अंधेरा जानबूझकर नहीं था। यह उत्पन्न छवि में पारदर्शिता के साथ एक बग था। तुलनात्मक कोड ने सोचा कि पारदर्शी काला होना चाहिए।
वोल्फहैमर

@trichoplax मैंने इसे केवल एक यादृच्छिक रंग की तुलना करने के लिए बदल दिया है।
वॉल्फहैमर

1
मैंने आपके कोड को एक jsfiddle में कॉपी किया और एक प्रयोग करने की कोशिश की। इसने अभिसरण को कुछ और तेज कर दिया। आप इसे आज़माना पसंद कर सकते हैं ... मैंने जो भी किया, वह लूप फ़ंक्शन की सामग्री को 1000 बार सामग्री को दोहराने के लिए लूप के साथ घेर रहा था। इसका अर्थ है कि माउस और कीबोर्ड ईवेंट केवल प्रत्येक पुनरावृति के बजाय प्रत्येक 1000 पुनरावृत्तियों के लिए जाँचे जाते हैं। आपका लूप काफी तेज है कि हर 1000 पुनरावृत्तियों में अभी भी माउस और कीबोर्ड उत्तरदायी है, और यह अभिसरण के लिए प्रतीक्षा समय बचाता है :)
ट्राइकोप्लाक्स

1
@tricholplax वाह उन सुझावों ने चीजों को बहुत तेज कर दिया। मुझे लगता है कि s / = 4 की आवश्यकता है, मुझे इसके साथ शांत रंग एनीमेशन नहीं मिलता है।
वोल्फहैमर

3

मेथेमेटिका

यह वास्तव में तेज नहीं है, लेकिन कम से कम यह पहचानने योग्य चित्र बनाता है, इसलिए मैं खुश हूं।

img = Import["http://i.stack.imgur.com/P7X6g.jpg"]
squigglesize = 20;
squiggleterb = 35;
colors = Import["http://i.stack.imgur.com/u9JAD.png"];
colist = Table[RGBColor[PixelValue[colors, {x, 1}]], {x, 28}];
imgdim0 = ImageDimensions[img];
curimg = Image[ConstantArray[0, Reverse[imgdim0]]];

rp := RandomInteger[squigglesize, 2] - squigglesize/2;
i = 0; j = 0;
Module[{imgdim = imgdim0, randimg, points, randcol, squigmid, st, 
  randist, curdist = curdist0, i = 0, j = 0},

 While[j < 10,
  squigmid = {RandomInteger[imgdim[[1]]], RandomInteger[imgdim[[1]]]};      
  While[i < 20,
   randcol = RandomChoice[colist];
   st = RandomInteger[squiggleterb, 2] - squiggleterb/2;
   points = {rp + squigmid + st, rp + squigmid + st, rp + squigmid + st, rp + squigmid + st};

   randimg = 
    Rasterize[
     Style[Graphics[{Inset[curimg, Center, Center, imgdim],
        {randcol, BezierCurve[Table[{-1, 0}, {4}] + points]},
        {randcol, BezierCurve[Table[{-1, 1}, {4}] + points]},
        {randcol, BezierCurve[Table[{0, -1}, {4}] + points]},
        {randcol, BezierCurve[points]},
        {randcol, BezierCurve[Table[{0, 1}, {4}] + points]},
        {randcol, BezierCurve[Table[{0, 2}, {4}] + points]},
        {randcol, BezierCurve[Table[{1, -1}, {4}] + points]},
        {randcol, BezierCurve[Table[{1, 0}, {4}] + points]},
        {randcol, BezierCurve[Table[{1, 1}, {4}] + points]},
        {randcol, BezierCurve[Table[{1, 2}, {4}] + points]},
        {randcol, BezierCurve[Table[{2, 0}, {4}] + points]},
        {randcol, BezierCurve[Table[{2, 1}, {4}] + points]}
       }, ImageSize -> imgdim, PlotRange -> {{0, imgdim[[1]]}, {0, imgdim[[2]]}}], 
      Antialiasing -> False], RasterSize -> imgdim];
   randist = ImageDistance[img, randimg];
   If[randist < curdist, curimg = randimg; curdist = randist; i = 0; 
    j = 0;];
   i += 1;
   ]; j += 1; i = 0;];
 Print[curimg]]

आउटपुट:

इनपुट उत्पादन

इनपुट उत्पादन

आउटपुट शायद अधिक पुनरावृत्तियों के साथ थोड़ा बेहतर हो सकता है, और अभी भी बहुत कुछ है जिसे मैं इसे गति देने / अभिसरण में सुधार करने की कोशिश कर सकता हूं, लेकिन अभी के लिए यह काफी अच्छा लगता है।


2

SmileBASIC

OPTION STRICT
OPTION DEFINT

DEF MSPAINT(IMAGE,WIDTH,HEIGHT,STEPS)
 'read color data
 DIM COLORS[28]
 COPY COLORS%,@COLORS
 @COLORS
 DATA &H000000,&H808080,&H800000
 DATA &H808000,&H008000,&H008080
 DATA &H000080,&H800080,&H808040
 DATA &H004040,&H0080FF,&H004080
 DATA &H8000FF,&H804000,&HFFFFFF
 DATA &HC0C0C0,&HFF0000,&HFFFF00
 DATA &H00FF00,&H00FFFF,&H0000FF
 DATA &HFF00FF,&HFFFF80,&H00FF80
 DATA &H80FFFF,&H8080FF,&HFF0080
 DATA &HFF8040

 'create output array and fill with white
 DIM OUTPUT[WIDTH,HEIGHT]
 FILL OUTPUT,&HFFFFFFFF

 VAR K
 FOR K=1 TO STEPS
  'Pick random position/color
  VAR X=RND(WIDTH -3)
  VAR Y=RND(HEIGHT-3)
  VAR COLOR=COLORS[RND(28)]

  'Extract average (really the sum) color in a 4x4 area.
  'this is less detailed than checking the difference of every pixel
  'but it's better in some ways...
  'corners are included so it will do SOME dithering
  'R1/G1/B1 = average color in original image
  'R2/G2/B2 = average color in current drawing
  'R3/G3/B3 = average color if brush is used
  VAR R1=0,G1=0,B1=0,R2=0,G2=0,B2=0,R3=0,G3=0,B3=0
  VAR R,G,B
  VAR I,J
  FOR J=0 TO 3
   FOR I=0 TO 3
    'original image average
    RGBREAD IMAGE[Y+J,X+I] OUT R,G,B
    INC R1,R
    INC G1,G
    INC B1,B
    'current drawing average
    RGBREAD OUTPUT[Y+J,X+I] OUT R,G,B
    INC R2,R
    INC G2,G
    INC B2,B
    'add the old color to the brush average if we're in a corner
    IF (J==0||J==3)&&(I==0||I==3) THEN
     INC R3,R
     INC G3,G
     INC B3,B
    ENDIF
   NEXT
  NEXT
  'brush covers 12 pixels
  RGBREAD COLOR OUT R,G,B
  INC R3,R*12
  INC G3,G*12
  INC B3,B*12

  'Compare
  BEFORE=ABS(R1-R2)+ABS(G1-G2)+ABS(B1-B2)
  AFTER =ABS(R1-R3)+ABS(G1-G3)+ABS(B1-B3)

  'Draw if better
  IF AFTER<BEFORE THEN
   FILL OUTPUT,COLOR, Y   *WIDTH+X+1,2 ' ##
   FILL OUTPUT,COLOR,(Y+1)*WIDTH+X  ,4 '####
   FILL OUTPUT,COLOR,(Y+2)*WIDTH+X  ,4 '####
   FILL OUTPUT,COLOR,(Y+3)*WIDTH+X+1,2 ' ##
  ENDIF
 NEXT

 RETURN OUTPUT
END

MSPAINT छवि% [] , चौड़ाई% , ऊँचाई% , चरण OUT आउटपुट% []

  • छवि% - 2D [y, x] छवि डेटा के साथ पूर्णांक सरणी (32 बिट ARGB प्रारूप (अल्फा पर ध्यान नहीं दिया जाता है))
  • चौड़ाई% - छवि चौड़ाई
  • ऊंचाई% - छवि ऊंचाई
  • कदम% - पुनरावृत्तियों की संख्या
  • आउटपुट% - आउटपुट सरणी, छवि% के समान।

यहाँ छवि विवरण दर्ज करें


क्या आप कुछ उदाहरण जोड़ सकते हैं?
ड्राम

हाँ, मैं जल्द ही कुछ जोड़ूंगा (हालांकि यह चित्रों को स्थानांतरित करने के लिए बहुत काम है, इसलिए मुझे अभी के लिए स्क्रीन की तस्वीरें लेनी
होंगी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.