diff --git a/src/BitmapSkin.js b/src/BitmapSkin.js index 63baf324e..b4b03d3b7 100644 --- a/src/BitmapSkin.js +++ b/src/BitmapSkin.js @@ -79,20 +79,31 @@ class BitmapSkin extends Skin { setBitmap (bitmapData, costumeResolution, rotationCenter) { const gl = this._renderer.gl; + // Preferably bitmapData is ImageData. ImageData speeds up updating + // Silhouette and is better handled by more browsers in regards to + // memory. + let textureData = bitmapData; + if (bitmapData instanceof HTMLCanvasElement) { + // Given a HTMLCanvasElement get the image data to pass to webgl and + // Silhouette. + const context = bitmapData.getContext('2d'); + textureData = context.getImageData(0, 0, bitmapData.width, bitmapData.height); + } + if (this._texture) { gl.bindTexture(gl.TEXTURE_2D, this._texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmapData); - this._silhouette.update(bitmapData); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureData); + this._silhouette.update(textureData); } else { // TODO: mipmaps? const textureOptions = { auto: true, wrap: gl.CLAMP_TO_EDGE, - src: bitmapData + src: textureData }; this._texture = twgl.createTexture(gl, textureOptions); - this._silhouette.update(bitmapData); + this._silhouette.update(textureData); } // Do these last in case any of the above throws an exception diff --git a/src/SVGSkin.js b/src/SVGSkin.js index 1054a280b..90e39081e 100644 --- a/src/SVGSkin.js +++ b/src/SVGSkin.js @@ -77,10 +77,14 @@ class SVGSkin extends Skin { this._textureScale = newScale; this._svgRenderer._draw(this._textureScale, () => { if (this._textureScale === newScale) { + const canvas = this._svgRenderer.canvas; + const context = canvas.getContext('2d'); + const textureData = context.getImageData(0, 0, canvas.width, canvas.height); + const gl = this._renderer.gl; gl.bindTexture(gl.TEXTURE_2D, this._texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._svgRenderer.canvas); - this._silhouette.update(this._svgRenderer.canvas); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureData); + this._silhouette.update(textureData); } }); } @@ -99,20 +103,28 @@ class SVGSkin extends Skin { this._svgRenderer.fromString(svgData, 1, () => { const gl = this._renderer.gl; this._textureScale = this._maxTextureScale = 1; + + // Pull out the ImageData from the canvas. ImageData speeds up + // updating Silhouette and is better handled by more browsers in + // regards to memory. + const canvas = this._svgRenderer.canvas; + const context = canvas.getContext('2d'); + const textureData = context.getImageData(0, 0, canvas.width, canvas.height); + if (this._texture) { gl.bindTexture(gl.TEXTURE_2D, this._texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._svgRenderer.canvas); - this._silhouette.update(this._svgRenderer.canvas); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureData); + this._silhouette.update(textureData); } else { // TODO: mipmaps? const textureOptions = { auto: true, wrap: gl.CLAMP_TO_EDGE, - src: this._svgRenderer.canvas + src: textureData }; this._texture = twgl.createTexture(gl, textureOptions); - this._silhouette.update(this._svgRenderer.canvas); + this._silhouette.update(textureData); } const maxDimension = Math.max(this._svgRenderer.canvas.width, this._svgRenderer.canvas.height); diff --git a/src/Silhouette.js b/src/Silhouette.js index 413d3b5bf..5ab109540 100644 --- a/src/Silhouette.js +++ b/src/Silhouette.js @@ -88,17 +88,27 @@ class Silhouette { * rendering can be queried from. */ update (bitmapData) { - const canvas = Silhouette._updateCanvas(); - const width = this._width = canvas.width = bitmapData.width; - const height = this._height = canvas.height = bitmapData.height; - const ctx = canvas.getContext('2d'); - - if (!(width && height)) { - return; + let imageData; + if (bitmapData instanceof ImageData) { + // If handed ImageData directly, use it directly. + imageData = bitmapData; + this._width = bitmapData.width; + this._height = bitmapData.height; + } else { + // Draw about anything else to our update canvas and poll image data + // from that. + const canvas = Silhouette._updateCanvas(); + const width = this._width = canvas.width = bitmapData.width; + const height = this._height = canvas.height = bitmapData.height; + const ctx = canvas.getContext('2d'); + + if (!(width && height)) { + return; + } + ctx.clearRect(0, 0, width, height); + ctx.drawImage(bitmapData, 0, 0, width, height); + imageData = ctx.getImageData(0, 0, width, height); } - ctx.clearRect(0, 0, width, height); - ctx.drawImage(bitmapData, 0, 0, width, height); - const imageData = ctx.getImageData(0, 0, width, height); this._data = new Uint8ClampedArray(imageData.data.length / 4); this._colorData = imageData.data;