Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added canvas capture plugin so we don't need to load from github
- Loading branch information
Showing
5 changed files
with
313 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/* | ||
* Canvas2Image v0.1 | ||
* Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com | ||
* MIT License [http://www.opensource.org/licenses/mit-license.php] | ||
*/ | ||
|
||
var Canvas2Image = (function() { | ||
// check if we have canvas support | ||
var oCanvas = document.createElement("canvas"), | ||
sc = String.fromCharCode, | ||
strDownloadMime = "image/octet-stream", | ||
bReplaceDownloadMime = false; | ||
|
||
// no canvas, bail out. | ||
if (!oCanvas.getContext) { | ||
return { | ||
saveAsBMP : function(){}, | ||
saveAsPNG : function(){}, | ||
saveAsJPEG : function(){} | ||
} | ||
} | ||
|
||
var bHasImageData = !!(oCanvas.getContext("2d").getImageData), | ||
bHasDataURL = !!(oCanvas.toDataURL), | ||
bHasBase64 = !!(window.btoa); | ||
|
||
// ok, we're good | ||
var readCanvasData = function(oCanvas) { | ||
var iWidth = parseInt(oCanvas.width), | ||
iHeight = parseInt(oCanvas.height); | ||
return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight); | ||
} | ||
|
||
// base64 encodes either a string or an array of charcodes | ||
var encodeData = function(data) { | ||
var i, aData, strData = ""; | ||
|
||
if (typeof data == "string") { | ||
strData = data; | ||
} else { | ||
aData = data; | ||
for (i = 0; i < aData.length; i++) { | ||
strData += sc(aData[i]); | ||
} | ||
} | ||
return btoa(strData); | ||
} | ||
|
||
// creates a base64 encoded string containing BMP data takes an imagedata object as argument | ||
var createBMP = function(oData) { | ||
var strHeader = '', | ||
iWidth = oData.width, | ||
iHeight = oData.height; | ||
|
||
strHeader += 'BM'; | ||
|
||
var iFileSize = iWidth*iHeight*4 + 54; // total header size = 54 bytes | ||
strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); | ||
strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); | ||
strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256); | ||
strHeader += sc(iFileSize % 256); | ||
|
||
strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset | ||
strHeader += sc(40, 0, 0, 0); // info header size | ||
|
||
var iImageWidth = iWidth; | ||
strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); | ||
strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); | ||
strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256); | ||
strHeader += sc(iImageWidth % 256); | ||
|
||
var iImageHeight = iHeight; | ||
strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); | ||
strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); | ||
strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256); | ||
strHeader += sc(iImageHeight % 256); | ||
|
||
strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel | ||
strHeader += sc(0, 0, 0, 0); // compression = none | ||
|
||
var iDataSize = iWidth*iHeight*4; | ||
strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); | ||
strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); | ||
strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256); | ||
strHeader += sc(iDataSize % 256); | ||
|
||
strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used | ||
|
||
var aImgData = oData.data, | ||
strPixelData = "", | ||
c, x, y = iHeight, | ||
iOffsetX, iOffsetY, strPixelRow; | ||
|
||
do { | ||
iOffsetY = iWidth*(y-1)*4; | ||
strPixelRow = ""; | ||
for (x = 0; x < iWidth; x++) { | ||
iOffsetX = 4*x; | ||
strPixelRow += sc( | ||
aImgData[iOffsetY + iOffsetX + 2], // B | ||
aImgData[iOffsetY + iOffsetX + 1], // G | ||
aImgData[iOffsetY + iOffsetX], // R | ||
aImgData[iOffsetY + iOffsetX + 3] // A | ||
); | ||
} | ||
strPixelData += strPixelRow; | ||
} while (--y); | ||
|
||
return encodeData(strHeader + strPixelData); | ||
} | ||
|
||
// sends the generated file to the client | ||
var saveFile = function(strData) { | ||
if (!window.open(strData)) { | ||
document.location.href = strData; | ||
} | ||
} | ||
|
||
var makeDataURI = function(strData, strMime) { | ||
return "data:" + strMime + ";base64," + strData; | ||
} | ||
|
||
// generates a <img> object containing the imagedata | ||
var makeImageObject = function(strSource) { | ||
var oImgElement = document.createElement("img"); | ||
oImgElement.src = strSource; | ||
return oImgElement; | ||
} | ||
|
||
var scaleCanvas = function(oCanvas, iWidth, iHeight) { | ||
if (iWidth && iHeight) { | ||
var oSaveCanvas = document.createElement("canvas"); | ||
|
||
oSaveCanvas.width = iWidth; | ||
oSaveCanvas.height = iHeight; | ||
oSaveCanvas.style.width = iWidth+"px"; | ||
oSaveCanvas.style.height = iHeight+"px"; | ||
|
||
var oSaveCtx = oSaveCanvas.getContext("2d"); | ||
|
||
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth); | ||
|
||
return oSaveCanvas; | ||
} | ||
return oCanvas; | ||
} | ||
|
||
return { | ||
saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) { | ||
if (!bHasDataURL) return false; | ||
|
||
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight), | ||
strMime = "image/png", | ||
strData = oScaledCanvas.toDataURL(strMime); | ||
|
||
if (bReturnImg) { | ||
return makeImageObject(strData); | ||
} else { | ||
saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData); | ||
} | ||
return true; | ||
}, | ||
|
||
saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) { | ||
if (!bHasDataURL) return false; | ||
|
||
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight), | ||
strMime = "image/jpeg", | ||
strData = oScaledCanvas.toDataURL(strMime); | ||
|
||
// check if browser actually supports jpeg by looking for the mime type in the data uri. if not, return false | ||
if (strData.indexOf(strMime) != 5) return false; | ||
|
||
if (bReturnImg) { | ||
return makeImageObject(strData); | ||
} else { | ||
saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData); | ||
} | ||
return true; | ||
}, | ||
|
||
saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) { | ||
if (!(bHasDataURL && bHasImageData && bHasBase64)) return false; | ||
|
||
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight), | ||
strMime = "image/bmp", | ||
oData = readCanvasData(oScaledCanvas), | ||
strImgData = createBMP(oData); | ||
|
||
if (bReturnImg) { | ||
return makeImageObject(makeDataURI(strImgData, strMime)); | ||
} else { | ||
saveFile(makeDataURI(strImgData, strMime)); | ||
} | ||
return true; | ||
} | ||
}; | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/** | ||
* Custom node which captures images of the scene canvas | ||
* | ||
* @author xeolabs / http://xeolabs.com | ||
* | ||
* <p>Usage example:</p> | ||
* | ||
* <pre> | ||
* someNode.addNode({ | ||
* type: "canvas/capture", | ||
* | ||
* // Optional image format, "jpeg" (default), "png" or "bmp" | ||
* format: "jpeg", | ||
* | ||
* // Optional image result size, defaults to current size of canvas at time of capture | ||
* width: 300, | ||
* height: 400 | ||
* }); | ||
* | ||
* scene.getNode("myCanvasCapture", | ||
* function (myCanvasCapture) { | ||
* | ||
* // Subscribe to captured image | ||
* myCanvasCapture.on("image", | ||
* function (data) { | ||
* var src = data.src; // Data URL | ||
* var width = data.width; // Width of image | ||
* var height = data.height; // Height of image | ||
* }); | ||
* | ||
* // Do capture | ||
* myCanvasCapture.capture({ | ||
* | ||
* // Optional dimensions of desired image, falls back on node config, | ||
* // or if not specified there, the current size of canvas | ||
* width: 500, | ||
* height: 400, | ||
* | ||
* // Optional format - falls back on node config, | ||
* // or if not specified there, "jpeg" | ||
* format: "jpeg" | ||
* }); | ||
* | ||
* </pre> | ||
*/ | ||
require([ | ||
|
||
// This prefix routes to the 3rd-party libs directory containing resources used by plugins | ||
"scenejsPluginDeps/canvas2image" | ||
], | ||
function () { | ||
|
||
SceneJS.Types.addType("canvas/capture", { | ||
|
||
construct:function (params) { | ||
this._format = params.format ? this._supportedFormat(params.format) : "jpeg"; | ||
this._width = params.width; | ||
this._height = params.height; | ||
}, | ||
|
||
capture:function (params) { | ||
|
||
params = params || {}; | ||
|
||
var scene = this.getScene(); | ||
scene.renderFrame({ force:true }); // HACK - need to fix need for this in SceneJS | ||
var canvas = scene.getCanvas(); | ||
|
||
var width = params.width || this._width || canvas.width; | ||
var height = params.height || this._height || canvas.height; | ||
|
||
var image; | ||
|
||
var format = params.format ? this._supportedFormat(params.format) : this._format; | ||
|
||
switch (format) { | ||
case "jpeg": | ||
image = Canvas2Image.saveAsJPEG(canvas, true, width, height); | ||
break; | ||
|
||
case "png": | ||
image = Canvas2Image.saveAsPNG(canvas, true, width, height); | ||
break; | ||
|
||
case "bmp": | ||
image = Canvas2Image.saveAsBMP(canvas, true, width, height); | ||
break; | ||
|
||
default: | ||
this.log("error", "format unsupported: " + format); | ||
return; | ||
} | ||
|
||
this.publish("image", { | ||
src:image.src, | ||
format:format, | ||
width:width, | ||
height:height | ||
}); | ||
}, | ||
|
||
_supportedFormat:function (format) { | ||
if (format != "jpeg" && format != "png" && format != "bmp") { | ||
this.log("error", "unsupported format for canvas/capture node: " + format | ||
+ " - supported types are 'jpeg', 'bmp' and 'png' - falling back on 'jpeg'"); | ||
return "jpeg"; | ||
} | ||
return format; | ||
} | ||
}); | ||
|
||
}); |
File renamed without changes.