2010-04-04 2 views
20

HTML 5 캔버스의 픽셀 조작을 사용하여 몇 가지 동적 인 시각적 효과를 시도하지만 CanvasPixelArray의 픽셀 설정이 엄청나게 느린 문제가 있습니다. 예를 들어HTML5의 CanvasPixelArray 값을 너무 느리게 설정하는 이유와 어떻게하면 더 빨리 할 수 ​​있습니까?

나는 코드가 같은 경우 :

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); 

크롬 계시와 프로파일, 그것은 CanvasPixelArray를 사용하지 않는 다음과 같은 코드보다 44 % 느리게 실행됩니다.

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); 

내 생각 엔이 둔화의 이유는 CanvasPixelArray에서 사용되는 자바 스크립트의 복식 및 내부 부호없는 8 비트 정수 사이의 변환에 의한 것입니다.

  1. 이 추측은 맞습니까?
  2. CanvasPixelArray에서 값을 설정하는 시간을 절약 할 수있는 방법이 있습니까?
+0

오래된 질문을 그리고 아마도 오래된 것입니다. 두 번째 예제에서는'imageData'에 아무 것도하지 않는 것처럼 보입니다 (예.값을'tempArray'에서'imageData'로 설정하지 않습니다)? – ZachB

+0

@ ZachB 예가 정확합니다. 당시 병 목으로 보인 CanvasPixelArray는 사용하지 않습니다. 이 문제를 해결 한 몇 가지 훌륭한 답변은 아래를 참조하십시오. – 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

버퍼가 무엇인지 이해할 수 없으며 imageData를 의미합니까? – kilianc

+0

Nixuz가 다른 곳에서 정의한 이미지로 복사하려는 데이터입니다. "데이터"변수는 이미지 데이터이므로 이미지 데이터가 아닙니다. 데이터를 자체에 복사하려고 시도하는 것은 의미가 없습니다. – jimr

0

"blitting"을하고있는 것처럼 보입니다. 따라서 drawImage 또는 all-at-once putImageData이 도움이 될 수 있습니다. 방대한 블리 팅 (blitting) 작업을 사용하는 대신 픽셀을 개별적으로 복사하는 데 25 만 회 반복하는 것은 자바 스크립트뿐만 아니라 훨씬 느려지는 경향이 있습니다.

+1

putImageData가 호출되면 실제 그리기가 한 번에 발생합니다. 각 "픽셀"(버퍼의 블록)을 루핑하여 버퍼 데이터를 처리하고 각각에 대해 몇 가지 사전 작업을 수행하는 방법은 기본적으로 데이터를 가져 오는 것으로 묘사 된 방법보다 훨씬 빠릅니다. 화면. 데이터 처리는 캔버스 픽셀 배열로 복사하는 것보다 훨씬 적은 시간이 소요된다는 사실이 충격적입니다. – 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

을이다 2D 객체 배열을 통해 루프 1 차원 배열 오프셋 계산보다 빠르며 객체가 없습니다. 그에 따라 서식을 지정하고 도움이되는지 확인하십시오 (내 테스트에서 20 배 빨랐습니다).

(최대 머리 :!이 스크립트는 당신이 그것을 실행하면 몇 분 동안 가만히 브라우저를 충돌하고 그 일을 할 수있다) 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

관련 문제