2010-04-04 11 views
20

मैं एचटीएमएल 5 कैनवास 'पिक्सेल मैनिपुलेशन का उपयोग करके कुछ गतिशील दृश्य प्रभाव करने की कोशिश कर रहा हूं, लेकिन मैं एक समस्या में भाग रहा हूं जहां कैनवास पिक्सेलएरे में पिक्सेल सेट करना हास्यास्पद रूप से धीमा है।एचटीएमएल 5 के कैनवास पिक्सेलएरे मूल्यों को हास्यास्पद रूप से धीमा क्यों कर रहा है और मैं इसे तेज़ी से कैसे कर सकता हूं?

उदाहरण के लिए अगर मैं कोड की तरह है:

imageData = ctx.getImageData(0, 0, 500, 500); 

for (var i = 0; i < imageData.length; i += 4){ 
    imageData.data[i] = buffer[i]; 
    imageData.data[i + 1] = buffer[i + 1]; 
    imageData.data[i + 2] = buffer[i + 2]; 
} 

ctx.putImageData(imageData, 0, 0); 

रूपरेखा क्रोम के साथ का पता चलता है, यह 44% के लिए निम्न कोड जहां CanvasPixelArray नहीं किया जाता है की तुलना में धीमी चलाता है।

tempArray = new Array(500 * 500 * 4); 
imageData = ctx.getImageData(0, 0, 500, 500); 

for (var i = 0; i < imageData.length; i += 4){ 
    tempArray[i] = buffer[i]; 
    tempArray[i + 1] = buffer[i + 1]; 
    tempArray[i + 2] = buffer[i + 2]; 
} 

ctx.putImageData(imageData, 0, 0); 

मेरा अनुमान है कि इस मंदी के लिए कारण जावास्क्रिप्ट डबल्स और आंतरिक अहस्ताक्षरित 8 बिट पूर्णांकों, CanvasPixelArray द्वारा प्रयोग किया जाता के बीच रूपांतरण की वजह से है।

  1. क्या यह अनुमान सही है?
  2. क्या कैनवास पिक्सेलएरे में मूल्य निर्धारित करने के समय को कम करने के लिए वैसे भी है? आप "blitting" किसी तरह का कर रहे हैं की तरह
+0

पुराना सवाल और शायद पुराना है, आपके दूसरे उदाहरण में आप 'छवि डेटा' (उदाहरण के लिए कुछ भी नहीं कर रहे हैंआप 'tempArray' से' imageData' 'तक मान सेट नहीं कर रहे हैं? – ZachB

+0

@ZachB उदाहरण सही है। यह कैनवास पिक्सेलएरे का उपयोग नहीं करता है जो उस समय बोतल की गर्दन लगती थी। समस्या को हल करने वाले कुछ महान प्रतिक्रियाओं के लिए नीचे देखें। – Nixuz

+0

हां, मैंने आपके प्रश्न को गलत तरीके से पढ़ा है। :) – ZachB

उत्तर

12

data पिक्सेल सरणी के संदर्भ को कैशिंग करने का प्रयास करें। आपकी मंदी को imageData.data पर अतिरिक्त संपत्ति तक पहुंच के लिए जिम्मेदार ठहराया जा सकता है। अधिक स्पष्टीकरण के लिए this article देखें।

उदा। यह तेज़ी से होना चाहिए कि आपके पास वर्तमान में क्या है।

var imageData = ctx.getImageData(0, 0, 500, 500), 
    data = imageData.data, 
    len = data.length; 

for (var i = 0; i < len; i += 4){ 
data[i] = buffer[i]; 
data[i + 1] = buffer[i + 1]; 
data[i + 2] = buffer[i + 2]; 
} 

ctx.putImageData(imageData, 0, 0); 
+0

आपको अजाक्सियन पर उपर्युक्त आलेख का संदर्भ भी मिलेगा, जिसमें अधिक टिप्पणियां बताती हैं कि यह संदर्भ पहुंच का मुद्दा है। http://ajaxian.com/archives/canvas-image-data-optimization-tip –

+0

मुझे समझ में नहीं आता कि बफर क्या है, क्या आपका मतलब छविडेटा था? – kilianc

+0

यह वह डेटा है जो निक्सुज़ छवि में प्रतिलिपि बनाना चाहता था - कहीं और परिभाषित किया गया था। यह imageData नहीं है, क्योंकि "डेटा" वैरिएबल छवि डेटा है - इसे स्वयं कॉपी करने की कोशिश करने के लिए यह समझ में नहीं आता है। – jimr

0

लग रहा है, तो हो सकता है drawImage या सभी-पर-एक बार putImageData मदद कर सकता है। भारी "ब्लिटिंग" परिचालनों का उपयोग करने के बजाए व्यक्तिगत रूप से पिक्सेल की प्रतिलिपि बनाने के लिए एक चौथाई लाख गुना लूपिंग, बहुत धीमी होती है - न केवल जावास्क्रिप्ट में ;-)।

+1

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

3

यदि यह आप में मदद करता है क्योंकि आप पिक्सल हेरफेर करना चाहते मैं नहीं जानता, लेकिन मेरे लिए, फ़ायरफ़ॉक्स 3.6.8 में, बस putImageData करने के लिए कॉल बहुत, बहुत धीमी थी, किसी भी पिक्सेल हेरफेर कर के बिना। मेरे मामले में, मैं बस छवि के पिछले संस्करण को पुनर्स्थापित करना चाहता था जो getImageData के साथ सहेजा गया था। बहुत धीमा।

इसके बजाय, मुझे इसके बजाय toDataUrl/drawImage का उपयोग करके अच्छी तरह से काम करने के लिए मिला। मेरे लिए यह काफी तेजी से कि मैं इसे एक MouseMove घटना से निपटने के भीतर कॉल कर सकते हैं काम कर रहा है:

सहेजने के लिए:

savedImage = new Image() 
savedImage.src = canvas.toDataURL("image/png") 

बहाल करने के लिए:

ctx = canvas.getContext('2d') 
ctx.drawImage(savedImage,0,0) 
0

अजीब तरह, 2 डी वस्तु सरणियों हैं के माध्यम से लूप एक 1 डी सरणी ऑफसेट कैल्क्स और कोई ऑब्जेक्ट से तेज़ नहीं है। तदनुसार प्रारूपित करें और देखें कि क्या यह मदद करता है (मेरे परीक्षणों में, यह 20x तेज था)।

(सिर ऊपर: इस स्क्रिप्ट अपने ब्राउज़र को नष्ट कर सकता है आप इसे चलाते हैं, तो कुछ ही मिनटों के लिए तैयार रहे और वह अपने काम करते हैं!) http://jsfiddle.net/hc52jx04/16/

function arrangeImageData (target) { 

var imageCapture = target.context.getImageData(0, 0, target.width, target.height); 
var imageData = { 
    data: [] 
}; 
imageData.data[0] = []; 
var x = 0; 
var y = 0; 
var imageLimit = imageCapture.data.length; 

for (var index = 0; index < imageLimit; index += 4) { 

    if (x == target.width) { 
     y++; 
     imageData.data[y] = []; 
     x = 0; 
    } 

    imageData.data[y][x] = { 
     red: imageCapture.data[index], 
     green: imageCapture.data[index + 1], 
     blue: imageCapture.data[index + 2], 
     alpha: imageCapture.data[index + 3] 
    }; 
    x++; 
} 
return imageData; 

} 


function codifyImageData (target, data) { 

var imageData = data.data; 

var index = 0; 
var codedImage = target.context.createImageData(target.width, target.height); 

for (var y = 0; y < target.height; y++) { 

    for (var x = 0; x < target.width; x++) { 

     codedImage.data[index] = imageData[y][x].red; 
     index++; 
     codedImage.data[index] = imageData[y][x].green; 
     index++; 
     codedImage.data[index] = imageData[y][x].blue; 
     index++; 
     codedImage.data[index] = imageData[y][x].alpha; 
     index++; 
    } 

} 

return codedImage; 

} 

अधिक जानकारी: http://discourse.wicg.io/t/why-a-straight-array-for-canvas-getimagedata/1020/6

संबंधित मुद्दे