HTML5 कैनवास में एकल पिक्सेल सेट करने का सबसे अच्छा तरीका क्या है?


184

एचटीएमएल 5 कैनवस के पास स्पष्ट रूप से एकल पिक्सेल सेट करने की कोई विधि नहीं है।

बहुत छोटी लाइन का उपयोग करके पिक्सेल सेट करना संभव हो सकता है, लेकिन फिर एंटीलाइजिंग और लाइन कैप हस्तक्षेप कर सकते हैं।

एक और तरीका एक छोटी ImageDataवस्तु बनाने और उपयोग करने का हो सकता है :

context.putImageData(data, x, y)

इसे लगाने के लिए।

क्या कोई ऐसा करने का एक कुशल और विश्वसनीय तरीका बता सकता है?

जवाबों:


292

दो सर्वश्रेष्ठ दावेदार हैं:

  1. एक 1 × 1 छवि डेटा बनाएं, रंग सेट करें और putImageDataस्थान पर:

    var id = myContext.createImageData(1,1); // only do this once per page
    var d  = id.data;                        // only do this once per page
    d[0]   = r;
    d[1]   = g;
    d[2]   = b;
    d[3]   = a;
    myContext.putImageData( id, x, y );     
    
  2. fillRect()पिक्सेल खींचने के लिए उपयोग करें (कोई अन्य समस्याएँ नहीं होनी चाहिए):

    ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
    ctx.fillRect( x, y, 1, 1 );
    

आप यहाँ इनकी गति का परीक्षण कर सकते हैं: http://jsperf.com/setting-canvas-pixel/9 या यहाँ https://www.measurethat.net/Benchmark/Show/1664/1

मैं उन ब्राउज़रों के खिलाफ परीक्षण करने की सलाह देता हूं जिनकी आप अधिकतम गति के लिए परवाह करते हैं। जुलाई 2017 तक, fillRect()फ़ायरफ़ॉक्स v54 और क्रोम v59 (Win7x64) पर 5-6 × तेज है।

अन्य, sillier विकल्प हैं:

  • getImageData()/putImageData()पूरे कैनवास पर उपयोग करना; यह अन्य विकल्पों की तुलना में लगभग 100 × धीमा है।

  • डेटा url का उपयोग करके और drawImage()इसे दिखाने के लिए उपयोग करके एक कस्टम छवि बनाना :

    var img = new Image;
    img.src = "data:image/png;base64," + myPNGEncoder(r,g,b,a);
    // Writing the PNGEncoder is left as an exercise for the reader
    
  • आप चाहते हैं कि सभी पिक्सल से भरा एक और img या कैनवास बनाने के लिए और भर में आप चाहते हैं drawImage()बस पिक्सेल पिक्सेल का उपयोग करने के लिए। यह संभवतः बहुत तेज़ होगा, लेकिन इसकी सीमा है कि आपको अपनी ज़रूरत के अनुसार पिक्सेल की पूर्व-गणना करने की आवश्यकता है।

ध्यान दें कि मेरे परीक्षण कैनवास संदर्भ को बचाने और पुनर्स्थापित करने का प्रयास नहीं करते हैं fillStyle; इससे fillRect()प्रदर्शन धीमा हो जाएगा । यह भी ध्यान दें कि मैं एक साफ स्लेट के साथ शुरू नहीं कर रहा हूं या प्रत्येक परीक्षण के लिए पिक्सेल के सटीक समान सेट का परीक्षण कर रहा हूं।


2
बग रिपोर्ट दर्ज करने के लिए मैं आपको एक और +10 देता! :)
अलनीतक

51
ध्यान दें कि मेरे जीपीयू और ग्राफिक्स ड्राइवरों के साथ मेरी मशीन fillRect()पर, क्रोम -24 पर 1x1 putimagedata की तुलना में अर्ध-हाल ही में लगभग 10x तेज हो गया है। इसलिए ... यदि गति महत्वपूर्ण है और आप अपने लक्षित दर्शकों को जानते हैं, तो एक पुराने उत्तर (यहां तक ​​कि मेरा) का शब्द न लें। इसके बजाय: परीक्षण!
मेंढक

3
कृपया जवाब अपडेट करें। आधुनिक ब्राउज़र पर भरण विधि बहुत तेज़ है।
बज़ी

10
"PNGEncoder लिखना पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है" मुझे जोर से हंसाया।
पास्कल गनेय

2
सभी महान कैनवस उत्तर मैं आपके द्वारा होने के लिए क्यों भूमि पर हूं? :)
डोमिनोज़

18

एक विधि जिसका उल्लेख नहीं किया गया है वह getImageData और फिर putImageData का उपयोग कर रही है।
जब आप एक बार में बहुत कुछ खींचना चाहते हैं तो यह तरीका अच्छा है।
http://next.plnkr.co/edit/mfNyalsAR2MWkccr

  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var canvasWidth = canvas.width;
  var canvasHeight = canvas.height;
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
  var id = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
  var pixels = id.data;

    var x = Math.floor(Math.random() * canvasWidth);
    var y = Math.floor(Math.random() * canvasHeight);
    var r = Math.floor(Math.random() * 256);
    var g = Math.floor(Math.random() * 256);
    var b = Math.floor(Math.random() * 256);
    var off = (y * id.width + x) * 4;
    pixels[off] = r;
    pixels[off + 1] = g;
    pixels[off + 2] = b;
    pixels[off + 3] = 255;

  ctx.putImageData(id, 0, 0);

13
@Alnitak मुझे आपके दिमाग को पढ़ने में सक्षम नहीं होने के लिए एक नकारात्मक दे रहा है, कम है..अन्य लोगों को यहाँ कई पिक्सेल की साजिश करने में सक्षम होने के लिए मिल सकता है। मैंने किया और फिर अधिक कुशल तरीके को याद किया, इसलिए इसे साझा किया।
PAEz

ग्राफिक्स के डेमो के लिए, जहां प्रत्येक पिक्सेल की गणना की जाती है, या समान है, बहुत सारे पिक्सेल को खींचते समय यह एक समझदार तरीका है। यह प्रत्येक पिक्सेल के लिए भरण का उपयोग करने से दस गुना तेज है।
सैम वाटकिंस

हाँ, इसने मुझे हमेशा गुदगुदाया कि अपवादित उत्तर कहता है कि यह विधि अन्य विधियों की तुलना में 100x धीमी है। यह सच हो सकता है यदि आपका प्लॉट 1000 से कम है, लेकिन वहां से यह विधि जीतना शुरू कर देती है और फिर अन्य तरीकों का वध करती है। यहाँ एक परीक्षण का मामला .... है measurethat.net/Benchmarks/Show/8386/0/...
पेज़

17

मैंने विचार नहीं किया था fillRect(), लेकिन जवाब ने मुझे इसके खिलाफ बेंचमार्क करने के लिए प्रेरित किया putImage()

एक (पुराने) मैकबुक प्रो पर क्रोम 9.0.597.84 के साथ यादृच्छिक स्थानों में 100,000 यादृच्छिक रूप से रंगीन पिक्सल्स रखना, 100ms से कम समय लेता है putImage(), लेकिन लगभग 900ms का उपयोग करना fillRect()। (बेंचमार्क कोड http://pastebin.com/4ijVKJcC पर )।

अगर इसके बजाय मैं छोरों के बाहर एक एकल रंग का चयन करता हूं और यादृच्छिक स्थानों पर उस रंग की साजिश करता putImage()हूं , तो 59ms बनाम 102ms लगते हैं fillRect()

ऐसा लगता है कि rgb(...)सिंटैक्स में सीएसएस रंग विनिर्देश को उत्पन्न करने और पार्स करने का ओवरहेड अधिकांश अंतर के लिए जिम्मेदार है।

कच्चे आरजीबी मूल्यों को सीधे ImageDataदूसरी तरफ एक ब्लॉक में डालने के लिए किसी स्ट्रिंग हैंडलिंग या पार्सिंग की आवश्यकता नहीं होती है।


2
मैंने एक प्लंकर जोड़ा जहां आप एक बटन पर क्लिक कर सकते हैं और प्रत्येक विधि (पुटमैज, फिलरक्ट) का परीक्षण कर सकते हैं और इसके अलावा लाइनटो विधि। यह दर्शाता है कि PutImage और FillRect कई बार बहुत करीब हैं लेकिन LineTo बेहद धीमा है। इसे यहां देखें: plnkr.co/edit/tww6e1VY2OCVY4c4ECy3?p=preview यह आपके महान पास्टबिन कोड पर आधारित है। धन्यवाद।
मूलांक

उस प्लंकर के लिए, मुझे लगता है कि PutImage FillRect (नवीनतम Chrome 63 पर) की तुलना में थोड़ा धीमा है, लेकिन जब मैंने LineTo आज़माया, तो PutImage FillRect की तुलना में काफी तेज़ है। किसी तरह वे हस्तक्षेप करते दिख रहे हैं।
mlepage

13
function setPixel(imageData, x, y, r, g, b, a) {
    var index = 4 * (x + y * imageData.width);
    imageData.data[index+0] = r;
    imageData.data[index+1] = g;
    imageData.data[index+2] = b;
    imageData.data[index+3] = a;
}

var index = (x + y * imageData. उपलब्धता) * 4;
user889030

1
putImageData() उस फ़ंक्शन के बाद कॉल करना चाहिए या संदर्भ संदर्भ द्वारा अपडेट होगा?
लुकास सूसा

7

चूंकि अलग-अलग ब्राउज़र अलग-अलग तरीकों को पसंद करते हैं, हो सकता है कि लोडिंग प्रक्रिया के एक हिस्से के रूप में सभी तीन तरीकों के साथ एक छोटा परीक्षण करना समझ में आता है, जो यह पता लगाने के लिए कि उपयोग करना सबसे अच्छा है और फिर पूरे एप्लिकेशन का उपयोग करें?


5

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

तो मूल रूप से 3 संभावित समाधान हैं:

  • रेखा के रूप में बिंदु बनाएं
  • बहुभुज के रूप में बिंदु बनाएं
  • वृत्त के रूप में बिंदु बनाएं

उनमें से प्रत्येक में अपनी कमियां हैं


लाइन

function point(x, y, canvas){
  canvas.beginPath();
  canvas.moveTo(x, y);
  canvas.lineTo(x+1, y+1);
  canvas.stroke();
}

ध्यान रखें कि हम दक्षिण-पूर्व दिशा की ओर आकर्षित कर रहे हैं, और यदि यह बढ़त है, तो समस्या हो सकती है। लेकिन आप किसी अन्य दिशा में भी आकर्षित कर सकते हैं।


आयत

function point(x, y, canvas){
  canvas.strokeRect(x,y,1,1);
}

या fillRect का उपयोग करते हुए तेज़ तरीके से क्योंकि रेंडर इंजन केवल एक पिक्सेल को भर देगा।

function point(x, y, canvas){
  canvas.fillRect(x,y,1,1);
}

वृत्त


हलकों के साथ समस्याओं में से एक यह है कि इंजन के लिए उन्हें प्रस्तुत करना कठिन है

function point(x, y, canvas){
  canvas.beginPath();
  canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
  canvas.stroke();
}

आयत के समान विचार जो आप भरण से प्राप्त कर सकते हैं।

function point(x, y, canvas){
  canvas.beginPath();
  canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
  canvas.fill();
}

इन सभी समाधानों के साथ समस्याएँ:

  • यह उन सभी बिंदुओं पर नज़र रखना मुश्किल है जिन्हें आप आकर्षित करने जा रहे हैं।
  • जब आप ज़ूम इन करते हैं, तो यह बदसूरत दिखता है।

यदि आप सोच रहे हैं, " एक बिंदु खींचने का सबसे अच्छा तरीका क्या है ? ", मैं भरे हुए आयत के साथ जाऊंगा। आप तुलनात्मक परीक्षण के साथ यहाँ मेरे jsperf देख सकते हैं ।


दक्षिण-पूर्व दिशा? क्या?
लोगनार्क

4

एक आयत के बारे में क्या? यह एक ImageDataवस्तु बनाने की तुलना में अधिक कुशल है ।


3
आपको ऐसा लगता है, और यह एक एकल पिक्सेल के लिए हो सकता है, लेकिन यदि आप छवि डेटा बनाते हैं और 1 पिक्सेल सेट करते हैं और फिर इसका उपयोग क्रोम की putImageDataतुलना fillRectमें 10x तेज होता है। (अधिक के लिए मेरा उत्तर देखें।)
मेंढक

2

एक आयत की तरह आकर्षित करें जैसे कि सिध्दिसिरिहक ने कहा!

ctx.fillRect (10, 10, 1, 1);

^ - x: 10, y: 10 पर 1x1 आयत बनाना चाहिए


1

हम्म, तुम भी सिर्फ 1 पिक्सेल की लंबाई के साथ 1 पिक्सेल चौड़ी लाइन बना सकते हैं और यह एक अक्ष के साथ दिशा की चाल बना सकता है।

            ctx.beginPath();
            ctx.lineWidth = 1; // one pixel wide
            ctx.strokeStyle = rgba(...);
            ctx.moveTo(50,25); // positioned at 50,25
            ctx.lineTo(51,25); // one pixel long
            ctx.stroke();

1
मैंने FillRect, PutImage और LineTo के रूप में पिक्सेल ड्रॉ लागू किया और इस पर plunker बनाया: plnkr.co/edit/tww6e1VY2OCVY4c4ECy3?p=prepreit इसे देखें, क्योंकि LineTo घातीय धीमा है। 0.25 सेकंड में 100,000 अंक अन्य 2 विधियां कर सकते हैं, लेकिन लाइनटॉ के साथ 10,000 अंक 5 सेकंड लगते हैं।
मूलांक

1
ठीक है, मैंने एक गलती की और मैं पाश को बंद करना चाहूंगा। LineTo कोड एक - बहुत महत्वपूर्ण पंक्ति याद कर रहा था - जो निम्न की तरह दिखता है: ctx.beginPath (); मैंने प्लंकर (मेरी अन्य टिप्पणी से लिंक पर) को अपडेट किया और उस एक पंक्ति को जोड़कर अब लाइनटॉ विधि को 0.5 सेकंड के औसत में 100,000 उत्पन्न करने की अनुमति देता है। सचमुच अद्भुत। इसलिए यदि आप अपना उत्तर संपादित करते हैं और उस लाइन को अपने कोड में जोड़ते हैं (ctx.lineWidth लाइन से पहले) मैं आपको बढ़ा दूंगा। मुझे आशा है कि आपको यह दिलचस्प लगा और मैं अपने मूल बग्गी कोड के लिए माफी माँगता हूँ।
मूलांक

1

Phrogz को पूरी तरह से उत्तर देने के लिए, के बीच एक महत्वपूर्ण अंतर है fillRect()और putImageData()
पहले का उपयोग करता संदर्भ आकर्षित करने के लिए अधिक से जोड़ने , एक आयत (नहीं एक पिक्सेल) का उपयोग कर फ़िलस्टाइल अल्फा मूल्य और संदर्भ globalAlpha और परिवर्तन मैट्रिक्स , लाइन टोपियां आदि ..
दूसरे की जगह एक पूरे पिक्सल के सेट (शायद एक है, लेकिन क्यों ;)
परिणाम अलग है जैसा कि आप jsperf पर देख सकते हैं ।


कोई भी एक समय में एक पिक्सेल सेट नहीं करना चाहता (मतलब इसे स्क्रीन पर आरेखण करना)। यही कारण है कि ऐसा करने के लिए कोई विशिष्ट एपीआई नहीं है (और ठीक ही तो)।
प्रदर्शन के अनुसार, यदि लक्ष्य एक तस्वीर उत्पन्न करना है (उदाहरण के लिए एक किरण-अनुरेखण सॉफ्टवेयर), तो आप हमेशा एक सरणी प्राप्त करना चाहते हैं getImageData()जिसके द्वारा एक अनुकूलित Uint8Array है। तब आप putImageData()प्रति सेकंड ONCE या कुछ बार कॉल करके उपयोग करते हैं setTimeout/seTInterval


मेरे पास एक मामला है जहां मैं एक छवि में 100k ब्लॉक डालना चाहता था, लेकिन 1: 1 पिक्सेल पैमाने पर नहीं। उपयोग करना fillRectदर्दनाक था क्योंकि क्रोम के h / w त्वरण की आवश्यकता होती है जो GPU के लिए व्यक्तिगत कॉल के साथ सामना नहीं कर सकता है। मैंने 1: 1 पर पिक्सेल डेटा का उपयोग करना समाप्त कर दिया और फिर वांछित उत्पादन प्राप्त करने के लिए CSS स्केलिंग का उपयोग किया। यह बदसूरत है :(
Alnitak

फ़ायरफ़ॉक्स 42 पर अपने लिंक किए गए बेंचमार्क को चलाने पर मुझे केवल 168 ऑप्स / सेकंड get/putImageDataमिलते हैं, लेकिन 194,893 के लिए fillRect1x1 image data125,102 ऑप्स / सेकंड है। इसलिए fillRectफ़ायरफ़ॉक्स में दूर से जीतता है। इसलिए 2012 और आज के बीच चीजें बहुत बदल गईं। हमेशा की तरह, कभी भी पुराने बेंचमार्क परिणामों पर भरोसा न करें।
मेक्की

12
मैं एक समय में एक पिक्सेल सेट करना चाहता हूँ। मैं इस सवाल के शीर्षक से अनुमान लगा रहा हूं कि अन्य लोग भी करते हैं
चस्मानी

1

फास्ट HTML डेमो कोड: SFML C ++ ग्राफिक्स लाइब्रेरी के बारे में मुझे जो पता है उसके आधार पर:

इसे UTF-8 एन्कोडिंग वाली HTML फ़ाइल के रूप में सहेजें और इसे चलाएं। रिफ्लेक्टर के लिए स्वतंत्र महसूस करें, मुझे सिर्फ जापानी चर का उपयोग करना पसंद है क्योंकि वे संक्षिप्त हैं और बहुत जगह नहीं लेते हैं

शायद ही आप एक मनमाना पिक्सेल सेट करना चाहते हैं और इसे स्क्रीन पर प्रदर्शित करना चाहते हैं। तो का उपयोग करें

PutPix(x,y, r,g,b,a) 

एक बैक-बफर के लिए कई मनमाना पिक्सेल खींचने की विधि। (सस्ते कॉल)

फिर दिखाने के लिए तैयार होने पर, कॉल करें

Apply() 

परिवर्तनों को प्रदर्शित करने की विधि। (महंगी कॉल)

नीचे पूर्ण .HTML फ़ाइल कोड:

<!DOCTYPE HTML >
<html lang="en">
<head>
    <title> back-buffer demo </title>
</head>
<body>

</body>

<script>
//Main function to execute once 
//all script is loaded:
function main(){

    //Create a canvas:
    var canvas;
    canvas = attachCanvasToDom();

    //Do the pixel setting test:
    var test_type = FAST_TEST;
    backBufferTest(canvas, test_type);
}

//Constants:
var SLOW_TEST = 1;
var FAST_TEST = 2;


function attachCanvasToDom(){
    //Canvas Creation:
    //cccccccccccccccccccccccccccccccccccccccccc//
    //Create Canvas and append to body:
    var can = document.createElement('canvas');
    document.body.appendChild(can);

    //Make canvas non-zero in size, 
    //so we can see it:
    can.width = 800;
    can.height= 600;

    //Get the context, fill canvas to get visual:
    var ctx = can.getContext("2d");
    ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
    ctx.fillRect(0,0,can.width-1, can.height-1);
    //cccccccccccccccccccccccccccccccccccccccccc//

    //Return the canvas that was created:
    return can;
}

//THIS OBJECT IS SLOOOOOWW!
// 筆 == "pen"
//T筆 == "Type:Pen"
function T筆(canvas){


    //Publicly Exposed Functions
    //PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE//
    this.PutPix = _putPix;
    //PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE//

    if(!canvas){
        throw("[NilCanvasGivenToPenConstruct]");
    }

    var _ctx = canvas.getContext("2d");

    //Pixel Setting Test:
    // only do this once per page
    //絵  =="image"
    //資  =="data"
    //絵資=="image data"
    //筆  =="pen"
    var _絵資 = _ctx.createImageData(1,1); 
    // only do this once per page
    var _  = _絵資.data;   


    function _putPix(x,y,  r,g,b,a){
        _筆[0]   = r;
        _筆[1]   = g;
        _筆[2]   = b;
        _筆[3]   = a;
        _ctx.putImageData( _絵資, x, y );  
    }
}

//Back-buffer object, for fast pixel setting:
//尻 =="butt,rear" using to mean "back-buffer"
//T尻=="type: back-buffer"
function T尻(canvas){

    //Publicly Exposed Functions
    //PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE//
    this.PutPix = _putPix;
    this.Apply  = _apply;
    //PEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE//

    if(!canvas){
        throw("[NilCanvasGivenToPenConstruct]");
    }

    var _can = canvas;
    var _ctx = canvas.getContext("2d");

    //Pixel Setting Test:
    // only do this once per page
    //絵  =="image"
    //資  =="data"
    //絵資=="image data"
    //筆  =="pen"
    var _w = _can.width;
    var _h = _can.height;
    var _絵資 = _ctx.createImageData(_w,_h); 
    // only do this once per page
    var _  = _絵資.data;   


    function _putPix(x,y,  r,g,b,a){

        //Convert XY to index:
        var dex = ( (y*4) *_w) + (x*4);

        _筆[dex+0]   = r;
        _筆[dex+1]   = g;
        _筆[dex+2]   = b;
        _筆[dex+3]   = a;

    }

    function _apply(){
        _ctx.putImageData( _絵資, 0,0 );  
    }

}

function backBufferTest(canvas_input, test_type){
    var can = canvas_input; //shorthand var.

    if(test_type==SLOW_TEST){
        var t = new T筆( can );

        //Iterate over entire canvas, 
        //and set pixels:
        var x0 = 0;
        var x1 = can.width - 1;

        var y0 = 0;
        var y1 = can.height -1;

        for(var x = x0; x <= x1; x++){
        for(var y = y0; y <= y1; y++){
            t筆.PutPix(
                x,y, 
                x%256, y%256,(x+y)%256, 255
            );
        }}//next X/Y

    }else
    if(test_type==FAST_TEST){
        var t = new T尻( can );

        //Iterate over entire canvas, 
        //and set pixels:
        var x0 = 0;
        var x1 = can.width - 1;

        var y0 = 0;
        var y1 = can.height -1;

        for(var x = x0; x <= x1; x++){
        for(var y = y0; y <= y1; y++){
            t尻.PutPix(
                x,y, 
                x%256, y%256,(x+y)%256, 255
            );
        }}//next X/Y

        //When done setting arbitrary pixels,
        //use the apply method to show them 
        //on screen:
        t尻.Apply();

    }
}


main();
</script>
</html>


-1

HANDY और पुट पिक्सेल (पीपी) समारोह (ES6) (पठन-पिक्सेल का प्रस्ताव यहाँ ):

let pp= ((s='.myCanvas',c=document.querySelector(s),ctx=c.getContext('2d'),id=ctx.createImageData(1,1)) => (x,y,r=0,g=0,b=0,a=255)=>(id.data.set([r,g,b,a]),ctx.putImageData(id, x, y),c))()

pp(10,30,0,0,255,255);    // x,y,r,g,b,a ; return canvas object

इस फ़ंक्शन का उपयोग putImageDataऔर प्रारंभिक भाग (पहली लंबी पंक्ति) है। इसके बजाय भीख मांगने पर s='.myCanvas'आप अपने कैनवास पर CSS चयनकर्ता का उपयोग करें।

मैं आपको मापदंडों को सामान्य करने के लिए चाहता हूँ 0-1 से मूल्य के लिए आपको डिफ़ॉल्ट मान a=255को बदलना चाहिए a=1और इसके साथ लाइन में होना चाहिए : id.data.set([r,g,b,a]),ctx.putImageData(id, x, y)से id.data.set([r*255,g*255,b*255,a*255]),ctx.putImageData(id, x*c.width, y*c.height)

ऊपर दिया गया आसान कोड, तदर्थ परीक्षण ग्राफिक्स एल्गोरिदम या अवधारणा का प्रमाण बनाने के लिए अच्छा है, लेकिन यह उत्पादन में उपयोग करने के लिए अच्छा नहीं है जहां कोड को पठनीय और स्पष्ट होना चाहिए।


1
खराब अंग्रेजी के लिए डाउन-वोट किया और एक लाइनर।
जेवियर

1
@xavier - अंग्रेजी मेरी मूल भाषा नहीं है और मैं अग्रेजी भाषाएं सीखने में अच्छा नहीं हूं, हालांकि आप मेरे उत्तर को संपादित कर सकते हैं और भाषा के कीड़े को ठीक कर सकते हैं (यह आप से सकारात्मक योगदान होगा)। मैंने इस वन-लाइनर को रखा क्योंकि यह आसान और उपयोग करने में आसान है - और उदाहरण के लिए छात्रों के लिए कुछ ग्राफिक्स एल्गोरिदम का परीक्षण करना अच्छा हो सकता है, हालांकि यह उत्पादन में उपयोग किए जाने के लिए अच्छा समाधान नहीं है जहां कोड पठनीय और स्पष्ट होना चाहिए।
कामिल Kiełczewski

3
@ KamilKiełczewski कोड पढ़ने योग्य और स्पष्ट होना छात्रों के लिए उतना ही महत्वपूर्ण है जितना कि पेशेवरों के लिए।
लोगन पिकअप

-2

putImageDataशायद देशी की तुलना में तेज है fillRect। मुझे ऐसा लगता है क्योंकि पांचवें पैरामीटर को अलग-अलग तरीके से असाइन किया जा सकता है (आयत रंग), एक स्ट्रिंग का उपयोग करके जिसकी व्याख्या की जानी चाहिए।

मान लीजिए कि आप ऐसा कर रहे हैं:

context.fillRect(x, y, 1, 1, "#fff")
context.fillRect(x, y, 1, 1, "rgba(255, 255, 255, 0.5)")`
context.fillRect(x, y, 1, 1, "rgb(255,255,255)")`
context.fillRect(x, y, 1, 1, "blue")`

तो, लाइन

context.fillRect(x, y, 1, 1, "rgba(255, 255, 255, 0.5)")`

सभी के बीच सबसे भारी है। fillRectकॉल में पाँचवाँ तर्क थोड़ा लंबा है।


1
5 वें तर्क के रूप में कौन सा ब्राउज़र एक रंग को पारित करने का समर्थन करता है? क्रोम के लिए मुझे context.fillStyle = ...इसके बजाय उपयोग करना था। developer.mozilla.org/en-US/docs/Web/API/…
iX3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.