From 33536f6d2503b82b1ad384f4f55782e0deab38ec Mon Sep 17 00:00:00 2001 From: Ruben de Laat Date: Mon, 20 Apr 2015 08:43:18 +0200 Subject: [PATCH] - Updated to SceneJS4.1.0 - Added canvas capture plugin so we don't need to load from github --- example1.html | 2 +- js/example1.js | 2 + lib/scenejs/plugins/lib/canvas2image.js | 198 +++++++++++++++++++++ lib/scenejs/plugins/node/canvas/capture.js | 112 ++++++++++++ lib/{scenejs-4.0 => scenejs}/scenejs.js | 0 5 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 lib/scenejs/plugins/lib/canvas2image.js create mode 100644 lib/scenejs/plugins/node/canvas/capture.js rename lib/{scenejs-4.0 => scenejs}/scenejs.js (100%) diff --git a/example1.html b/example1.html index 209608be..d45b066d 100644 --- a/example1.html +++ b/example1.html @@ -16,7 +16,7 @@ - + diff --git a/js/example1.js b/js/example1.js index 11b2f40b..ec45044f 100644 --- a/js/example1.js +++ b/js/example1.js @@ -7,6 +7,8 @@ $(function() o.viewer = null; o.bimServerApi = null; + SceneJS.configure({ pluginPath: "lib/scenejs/plugins" }); + function showSelectProject() { $(this.window).resize(function(e) { o.viewer.resize($('div#viewport').width(), $('div#viewport').height()); diff --git a/lib/scenejs/plugins/lib/canvas2image.js b/lib/scenejs/plugins/lib/canvas2image.js new file mode 100644 index 00000000..d63c904a --- /dev/null +++ b/lib/scenejs/plugins/lib/canvas2image.js @@ -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 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; + } + }; +})(); \ No newline at end of file diff --git a/lib/scenejs/plugins/node/canvas/capture.js b/lib/scenejs/plugins/node/canvas/capture.js new file mode 100644 index 00000000..7d753afc --- /dev/null +++ b/lib/scenejs/plugins/node/canvas/capture.js @@ -0,0 +1,112 @@ +/** + * Custom node which captures images of the scene canvas + * + * @author xeolabs / http://xeolabs.com + * + *

Usage example:

+ * + *
+ * 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"
+ *        });
+ *
+ * 
+ */ +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; + } + }); + + }); \ No newline at end of file diff --git a/lib/scenejs-4.0/scenejs.js b/lib/scenejs/scenejs.js similarity index 100% rename from lib/scenejs-4.0/scenejs.js rename to lib/scenejs/scenejs.js