GetSubRaster and show in another canvas PaperJS - javascript

I am new to JavaScript and PaperJS. What I am trying to do is:
1) Load image to canvas using raster - done
var imageCanvas = document.getElementById('image-canvas');
var drawCanvas = document.getElementById('draw-canvas');
var img = document.getElementById('img');
imageCanvas.width = img.width;
imageCanvas.height = img.height;
var scope = new paper.PaperScope();
scope.setup(drawCanvas);
scope.setup(imageCanvas);//this will be active
var views = [2];
views[0] = scope.View._viewsById['image-canvas'];
views[1] = scope.View._viewsById['draw-canvas'];
views[0]._project.activate(); //making sure we are working on the right canvas
raster = new paper.Raster({source:img.src, position: views[0].center});
2) get the sub raster of the image; the rectangle is drawn by the user using mouse drag events. But for the sake of convenience lets say I have a rectangle at position (10,10) and dimensions (100,100)
3) get the sub raster and show the preview in other drawcanvas
views[1]._project.activate();// activating draw-canvas
var subras = raster.getSubRaster(new paper.Path.Rectangle(new paper.Point(10,10), new paper.Size(100,100))); //Ignore if the rectangle inside is not initialized correctly
But, nothing happens on the draw-canvas.
I also tried using
var subrasdata = raster.getSubRaster(new paper.Path.Rectangle(new paper.Point(10,10), new paper.Size(100,100))).toDataURL();
but it gives me
Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
Is there any other way to get the sub raster and pasting it in other canvas?

Instead of getSubRaster() I used Raster#getSubCanvas and Context#drawImage to paste in new canvas. So in short
canvasSrc = raster.getSubCanvas(rect);
destinationCanvasContext.drawImage(canvasSrc,0,0);

Related

Tainted canvases may not be exported error on chrome when i reload the page

I am making paint like web application using canvas, it is working properly on Firefox but when I reload the page on chrome and use .ToDataURL function it gives me an error of Tainted canvases may not be exported
canvas = document.getElementById('can');
ctx = canvas.getContext("2d");
widthOfCanvas = canvas.width;
highOfCanvas = canvas.height;
var image = new Image();
image.src='https://scontent.fkhi9-1.fna.fbcdn.net/v/t1.0-9/53169476_2381573508543072_5059610343865581568_n.png?_nc_cat=102&_nc_ht=scontent.fkhi9-1.fna&oh=bad33f4d78d743ed41c3455dcde6eeae&oe=5CE3CD71';
image.crossOrigin="anonymous";
console.log(image.onload)
image.onload = function(){
ctx.drawImage(image, 0, 0 ,widthOfCanvas,highOfCanvas);
}

EaseJS applying Color filter to Bitmap

I use easeJS in the implementation of the game robolucha, currently we display different colors of the characters by using shapes under transparent images.
We want to use Bitmaps and apply color filters to it.
Sadly the ColorFilter is not working.
The Fiddle is here for the code : https://jsfiddle.net/athanazio/7z6mqnrk/
And here is the code I´m using
var stage = new createjs.Stage("filter");
var head = new createjs.Container();
head.x = 300;
head.y = 300;
head.regX = 100;
head.regY = 100;
var path = "https://raw.githubusercontent.com/hamilton-lima/javascript-samples/master/easejs/colorfilter/";
var layer1 = new createjs.Bitmap(path + "layer1-green.png");
layer1.image.onload = function(){
layer1.filters = [ new createjs.ColorFilter(0, 0, 0, 1, 0, 0, 255, 1) ];
layer1.cache(0,0,200,200);
}
var layer2 = new createjs.Bitmap(path + "layer2.png");
head.addChild(layer1);
head.addChild(layer2);
stage.addChild(head);
createjs.Ticker.addEventListener("tick", headTick);
function headTick() {
head.rotation += 10;
}
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick() {
stage.update();
}
The ColorFilter does not work in this example because the image is being loaded cross-domain. The browser will not be able to read the pixels to apply the filter. I am not exactly sure why there is no error in the console.
EaselJS has no mechanism to automatically handle cross-origin images when it creates images behind the scenes (which it does when you pass a string path). You will have to create the image yourself, set the "crossOrigin" attribute, and then set the path (in that order). Then you can pass the image into the Bitmap constructor.
var img = document.createElement("img");
img.crossOrigin = "Anonymous";
img.onload = function() {
// apply the filter and cache it
}
img.src = path + "layer1.png";
layer1 = new createjs.Bitmap(img);
You don't have to wait for the image to load to create the Bitmap and apply the filter, but you will have to wait to cache the image.
This fix also requires a server that sends a cross-origin header, which git does. Here is an updated fiddle with that change. Note that if your image is loaded on the same server, this is not necessary.
https://jsfiddle.net/7z6mqnrk/10/
Cheers.

Firefox SVG2Blob not working as expected

I'm working with SVG text paths which I need to convert to regular HTML canvas. For that I'm converting SVG to a blob file and "downloading" it as an image. However it seems that while converting SVG to blob firefox breaks somewhere and text path is lost completely in the process.
Here's a fiddle of the problem: http://jsfiddle.net/ne5s2r1d/
var image = new Image();
var serializer = new XMLSerializer();
var data = serializer.serializeToString(document.getElementById("w3SVG"));
var blob = new Blob([data], {
type: 'image/svg+xml'
});
var DOMURL = window.URL || window.webkitURL || window;
var url = DOMURL.createObjectURL(blob);
image.onload = function () {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = canvas.height = 256;
document.body.appendChild(canvas);
ctx.drawImage(image, 20, 20);
DOMURL.revokeObjectURL(url);
}
image.src = url;
var canvas2 = document.createElement("canvas");
var ctx2 = canvas2.getContext("2d");
document.body.appendChild(canvas2);
It works with IE10+, Opera, Chrome but not firefox. (Current stable releases) It seems that firefox completely ignores the path element.
Any ideas on how to solve this? I tried Canvg but it doesn't support text paths and Kinetic seems to create rendering artifacts in firefox not to mention it's missing some of the key SVG features.
I know no good solution for this to work cross-browser.
However for Firefox and webkit browsers, you could try to pass directly the url encoded data to an image src.
(with the header set as data:image/svg+xml; charset=utf8 ,)
Then draw it in your canvas.
It should keep the xlink references, but IE will taint the canvas so you won't be able to access its data.
However, you can let the user right click on the canvas and save picture as….
Here is a little script that handles the full process :
function svgToPngDataURL(svg){
var svgDocType = document.implementation.createDocumentType('svg', "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
var svgDoc = document.implementation.createDocument ('http://www.w3.org/2000/svg', 'svg', svgDocType);
svgDoc.replaceChild(svg.cloneNode(true), svgDoc.documentElement);
var svgData = (new XMLSerializer()).serializeToString(svgDoc);
var header = 'data:image/svg+xml; charset=utf8 ,';
var img = new Image();
img.onload = function(){
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0,0);
try{
var data = canvas.toDataURL();
}
catch(ie){
document.body.appendChild(canvas);
displayIEerror();
return;
}
doWhateverWith(data);
}
img.src = header+encodeURIComponent(svgData);
}
The main problem of this is that if you have to support IE, there is no other way to know whereas it has tainted the canvas or not that a try{}catch().
Thus, toDataURL() can be really consumptive and it may be a bad idea to do it in a try catch, badly garbage collected by browsers.
So if you have a way to know that you are using IE before, avoid it and if you have to do it multiple time on the same page, add a flag so it occurs only once.

How convert downloaded inline image into Base64 on client side

Is there any technique to convert images that have already been downloaded – inline JPEG/GIF/etc. images that occur in a webpage – into Base64 data using client-side JavaScript?
I am not talking about how to transform an image into Base64 using other means (server-side, online tools, etc.).
These are the constraints for my particular use case:
The image is on screen now, right in the page, in front of person. It has already been downloaded in a data sense.
The conversion from raw image data has to be done client-side.
The images in question are from arbitrary domains. That is, they may or may not, be of same origin domain.
The user, if needed (if helpful to solution), can give additional permissions (for example, a FF toolbar install to help skirt cross-domain and other issues). That is, code can be given special endorsement on the client side if that helps solve the issue.
The end goal is to transform all images on the page (in the DOM) into Base64 data inside of JavaScript. Put another way, every image the user can see on the page has been converted into a JavaScript variable of some sort that contains the Base64 data.
So far I see no posts that stay inside of all the above constraints.
I think this is close to what you are looking for but the only problem is that it only works for locally hosted images and HTML5 only.
function toURL(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
var s = canvas.toDataURL();
return s.substring(s.indexOf(","));
}
var test = document.getElementById("myImage");
console.log(toURL(test));
You can trick javascript into thinking an image is from your domain with the following code.
image.php
<?php
$image = getAnImagePathAndTypeFromTheDatabaseByID($_GET["id"]);
//returns something like
//array("path" => "http://www.anotherwebsite.com/image.png", "type" => "png")
header("Content-type: image/$image[type]");
echo file_get_contents($image["path"]);
?>
Then just navigate to image.php?id=1 for example.
For it to work in cross-domain client-side you need to call the image with the attribute crossorigin = "true", or, add a line in the Logan Murphy code:
function toURL(image) {
image.setAttribute('crossOrigin', 'anonymous');
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
var s = canvas.toDataURL();
return s.substring(s.indexOf(","));
}
I use this code:
// image-to-uri.js v1
// converts a URL of an image into a dataURI
function imageToURI(url, callback) {
// Create an empty canvas and image elements
let canvas = document.createElement('canvas');
let img = document.createElement('img');
img.onload = function () {
let ctx = canvas.getContext('2d');
// match size of image
canvas.width = img.naturalWidth || img.width;
canvas.height = img.naturalHeight || img.height;
// Copy the image contents to the canvas
ctx.drawImage(img, 0, 0);
// Get the data-URI formatted image
callback(null, canvas.toDataURL('image/png'));
};
img.ononerror = function () {
callback(new Error('FailedToLoadImage'));
};
// canvas is not supported
if (!canvas.getContext) {
setTimeout(callback, 0, new Error('CanvasIsNotSupported'));
} else {
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
};
};
which is based on this https://github.com/HenrikJoreteg/image-to-data-uri.js/blob/master/image-to-data-uri.js

Restore canvas with base64 string

Whenever i first loaded the page. The image doesn't get restored but once i load the page and i hit F5. then it works. i'm not where whats wrong with my code.
// variable r contains the base64 string which is retrieved via a ajax call.
var myImage = new Image();
myImage.src = r;
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(myImage, 0, 0);
Ok. Instead of calling the ajax automatically when the page is loaded, i manually triggered the ajax call via a button, still i get the same result.
The base64 strings is retrieved successfully and imaged is not loaded. but when i clicked the button for a second time. the image is than loaded.
var myImage = new Image();
myImage.src = r;
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
// wait for it to load before calling draw
myImage.onload = function() {
ctx.drawImage(myImage, 0, 0);
}

Categories

Resources