I'm working on the browser-based tool for media distributors that require some manipulation with video.
I have HTML5 video player with video loaded from another domain (ex. http://video.com). Domain returns the following headers for the video (tries ...-Origin with * and with specific domain name):
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: *
The video tag is like this:
<video crossorigin="anonymous" src="http://video.com/video.mp4"></video>
JS I run is the following:
// meida is a reference to <video> tag
var
imgData,
width = media.videoWidth,
height = media.videoHeight,
canvas = document.createElement("canvas"),
context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
context.fillRect(0, 0, width, height);
context.drawImage(media, 0, 0, width, height);
imgData = canvas.toDataURL('image/png'); // line where IE throws DOMException named 'Security error'
The code works in all browsers except IE family. I've tried it on IE 11.
I understand that in this case canvas becomes tainted while it should not.
Does anybody know any way to make it work? I saw some workarounds for images but it doesn't work in my case with video.
PS: I've seen the answer Canvas.toDataURL() working in all browsers except IE10 but it is quite old and is related to images. I hope things changed since then.
I was trying to export pdf of page which includes highcharts.
I was getting same problem with IE when trying to load svg data on canvas, same security error.
I fixed this issue using canvg.js
just include canvg library files,
Add canvas on html page,
<canvas id="canvas" width="1000px" height="600px"></canvas>
use below method,
canvg(document.getElementById('canvas'), xml);
It worked for me in all browsers including IE.
By using fabric js "Security Error" in IE 11 will be gone.
var
imgData,
width = media.videoWidth,
height = media.videoHeight,
canvas = document.createElement("canvas"),
fabCanvas = new fabric.Canvas('c'),
context = fabCanvas.getContext('2d');
canvas.width = width;
canvas.height = height;
fabCanvas.fillRect(0, 0, width, height);
fabCanvas.drawImage(media, 0, 0, width, height);
imgData = fabCanvas.toDataURL({format: "png"});
Related
I have a requirement to take the canvas from a webpage and convert it to PDF in the backend so it can be saved on the server and downloaded & printed at a later time at 600 DPI.
I have followed this question, and I have a working prototype of the code: AJAX call to send the canvas to backend in Base64 and then a Java function to convert it to PDF.
However, the problem is that the quality of the image is dependent on the screen/browser window size the user has when he clicks the button to trigger the image creation - a fullscreen browser will create a higher-res image than a partial window browser. Example: Both taken on my PC but on the latter the window is about half the screen size.
I was thinking of somehow creating the canvas on a headless browser with preset size, and that would at least make the quality consistent across users, but I have no idea how to dynamically change the image so I can keep it at 600 DPI no matter the paper size the user chooses to use.
Do I have to draw the canvas shapes directly onto PDF? I know that would fulfill the DPI requirement, but is that even possible to do from an AngularJS/Java stack?
You can decide the proper size for the canvas and then modify the way it's displayed via CSS. Here, the final size is set as 2000x2000 and it will be saved as such (by clicking on it), regardless of the viewport size:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Draw the ellipse
ctx.beginPath();
ctx.lineWidth = 10;
ctx.ellipse(1000, 1000, 500, 800, Math.PI / 4, 0, 2 * Math.PI);
ctx.stroke();
// Draw the ellipse's line of reflection
ctx.beginPath();
ctx.setLineDash([5, 5]);
ctx.moveTo(0, 2000);
ctx.lineTo(2000, 0);
ctx.stroke();
canvas.addEventListener('click', function (e) {
var dataURL = canvas.toDataURL('image/png');
var link = document.createElement("a");
link.download = "finalsize.png";
link.href = dataURL;
link.click();
});
<body style="display:flexbox">
<canvas id="canvas" width="2000" height="2000" style="width:100%; "></canvas>
</body>
I basically want to transform my SVG into a PNG image. So I turn the SVG into an SVG image and try to draw that on a canvas to be able to get it as a PNG via the toDataURL() method. This works fine in Chrome, but in Firefox it produces a very uninformative error: NS_ERROR_NOT_AVAILABLE
After searching and experimenting a bit, I tried a different SVG source and all of a sudden everything worked fine. Any ideas what could cause the method to work fine for the first SVG string but fail for the second one? How can I change my SVG so that it will work?
Fiddle: http://jsfiddle.net/3AXwb/
var image = new Image();
image.src = 'data:image/svg+xml,' + escape(xml);
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
document.getElementById('container').appendChild(canvas);
context.drawImage(image, 0, 0);
}
Add a width attribute to the outer <svg> element. E.g. width="450"
The first case has width and height, the second only height and Firefox currently required both width and height to be present.
I try to render a local image loaded with a FileReader object on a Canvas on Safari Mobile on iOS6. But every image with data-URL gets rendered vertically scaled. Is this a bug? On Chrome it's rendered correctly.
Demo Script
ScreenShot from iOS6 (above: Canvas, below: Original Image)
Is there any way to work-around this bug? Is this a bug?
If I resize the image on the device first with the "PhotoWizard" App (scale it down to 720px width), the Canvas renders it correctly. It seems to be a problem with image size or images taken with the Camera App:
Working Demo Script
Tried suggestions from Jake Archibald, looks a bit better, but still gets vertically scaled:
Modified Demo Script
ScreenShot from iOS6
I tried it today on a Galaxy Nexus with Android 4.1.1 installed. Works like expected, so this really looks like a mobile Safari issue:
ScreenShot from Android 4.1.1
This might be related to the restriction which resides in iOS Safari resource limitation. According to following link, JPEG files over 2M pixels will be subsampled.
https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW15
I'm doubting that canvas in Safari cannot deal with this subsampling correctly.
I've created some workaround detecting whether the image is subsampled or not and stretching it to original size.
https://github.com/stomita/ios-imagefile-megapixel
var cnv = document.createElement("canvas");
ctx = cnv.getContext("2d");
image = new Image();
image.src = src;
image.onload = function() {
var size = scaleSizeRatio(image.width,image.height);
cnv.width = size[0];
cnv.height = size[1];
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width , image.height);
var div = container;
div.appendChild(cnv);
}
ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, image.width , image.height); This function will fix the squeezing issue in iPod more than 3Mb. First if your image is more than 3Mb then calculate the scaled width and height for the image and set that width and height to the canvas. Then call the drawImage function. It will give the final image what you expected...
I'm drawing a video on a canvas, this works fine with Safari / Chrome / Firefox / Opera, but on the iPad, even though the video plays, (correct codec, etc) it is never rendered on the canvas,
Basically I just call :
canvas.getContext("2d").drawImage(video, 0, 0);
when the video is playing, and stop doing this when the video is paused or ended.
Is there anything else I should consider? Like clearing the canvas?
For now safari on iPad is not supporting this feature. There are some limits on the attributes and events of canvas tag and video tag of HTML5 particularly on iPad. The attributes and events of canvas and video tags which work fine on desktop browsers wont work on iPad. This is my personal experience too.
See Putting Video on Canvas
You basically can’t pass a video object to the canvas drawImage method. Apple suggests having the video positioned behind the canvas but this won’t help if you want to manipulate the video somehow.
Have you tried wrapping it inside the requestAnimationFrame() function.
<video src="YourSrcFile.webm" autolay muted></video>
// Fallback to mp4 if not supported.
<canvas></canvas>
const video = document.querySelector("video"); // Offscreen Canvas.
const canvas = document.querySelector("canvas"); // Onscreen Canvas.
canvas.style.zIndex = '50';
const ctx = canvas.getContext("2d");
video.addEventListener('play',()=>{
function step() {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
requestAnimationFrame(step)
}
requestAnimationFrame(step);
})
Make sure to Match both the onscreen & offscreen canvas to the original videos aspect ratio otherwise the extra calculations make it laggy & poor performance..
You can use Transform Scale inside your css to resize it aslong as its proportionately. Which doesn't seem to make it glitchy, but I'd suggest converting the video from mp4, avi or other file type to webm..
just used this for a vjloop and its running smooth.
Try these and see if it makes any difference..
<script>
document.addEventListener('DOMContentLoaded', function(){
var v = document.getElementById('v');
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
var cw = Math.floor(canvas.clientWidth / 100);
var ch = Math.floor(canvas.clientHeight / 100);
canvas.width = cw;
canvas.height = ch;
v.addEventListener('play', function(){
draw(this,context,cw,ch);
},false);
},false);
function draw(v,c,w,h) {
if(v.paused || v.ended) return false;
c.drawImage(v,0,0,w,h);
setTimeout(draw,20,v,c,w,h);
}
</script>
Given a PNG in a web context with some transparent pixels and some non-transparent pixels, is there a way in Javascript to determine if a user has clicked on a non-transparent pixel? A webkit-only solution would be perfectly acceptable.
1) Create HTML5 canvas of same size as your image
2) Get Canvas's context, drawImage(yourImage, 0, 0)
3) d = context.getImageData(0, 0, w of img, h of img)
4) d.data[(y*width+x)*4+3] for the alpha
canvas = document.createElement("canvas"); //Create HTML5 canvas: supported in latest firefox/chrome/safari/konquerer. Support in IE9
canvas.width = img.width; //Set width of your rendertarget
canvas.height = img.height; // \ height \ \ \
ctx = canvas.getContext("2d"); //Get the 2d context [the thing you draw on]
ctx.drawImage(img, 0, 0); //Draw the picture on it.
id = ctx.getImageData(0,0, img.width, img.height); //Get the pixelData of image
//id.data[(y*width+x)*4+3] for the alpha value of pixel at x,y, 0->255
I know these things are out of fashion these days, but HTML image maps are still valid, and can accomplish adding hit targets to nearly-arbitrary shapes within an image. If you don't actually want to reload another page on click, you could probably change the anchor in the URL with this technique and pick up the change with a Javascript interval.
Canvas is the way to go for this purpose. But also remember that older internet explorer versions will not be capable of the getImageData() function. Even if you include excanvas.
I made a small jquery plugin exactly for this purpose, maybe it will help you solving your problem without to completely reinvent the wheel. http://www.cw-internetdienste.de/pixelselection/