There must be a way to do this. I have drawn a shape with the html5 canvas and I would like to blur it. As far as I know there is no native method so I assume a js library is needed. The problem is most libraries only blur images like this one for example. Is this possible?
myContext.filter = 'blur(10px)';
The CanvasRenderingContext2D.filter property of the Canvas 2D API provides filter effects like blurring or gray-scaling. It is similar to the CSS filter property and accepts the same functions. https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter
it's still experimental but is supported by chrome & firefox atm.
You can use CSS to blur the canvas. If it's just the shape you want to blur then the shape will need to be on its own separate layer (canvas), which you could create on the fly.
Example:
canvas.style.webkitFilter = "blur(3px)";
You can un-blur the canvas again with:
canvas.style.webkitFilter = "blur(0px)";
This is probably the fastest (and simplest) way to blur a canvas – especially for mobile devices.
For a fast blur that is almost Gaussian I'd recommend StackBlur:
http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
Alternatively you could use this Superfast Box Blur with 2 iterations:
http://www.quasimondo.com/BoxBlurForCanvas/FastBlurDemo.html
The pixastic library example you've linked to should actually work with a canvas element as the first argument rather than an image.
By default the pixastic library will try to replace the node you pass in with the canvas element that it creates. To prevent it from doing so you can include an option to specify to leave the DOM node and include a callback to handle the returned data yourself. Something like this:
Pixastic.process(canvas, "blur", { leaveDOM: true }, function(img) {
canvas.getContext('2d').drawImage(img, 0, 0);
});
Alternatively, if you don't want to depend on a library, you can implement a blur yourself using getImageData(), manipulating the returned pixel data and using putImageData() to draw the blurred image back to the canvas.
One other thing to note is that individual pixel manipulation is slow and may not work well for large images. If that's a problem, you might try scaling the image down and scaling back up for a quickly done blur like effect. Something like this:
ctx.drawImage(canvas, 0, 0, canvas.width / 2, canvas.height / 2);
ctx.drawImage(canvas, 0, 0, canvas.width / 2, canvas.height / 2, 0, 0, canvas.width, canvas.height);
https://github.com/nodeca/glur - it implements gaussian blur via IIR filter. See demos.
Related
I want to generate a blurred image from a normal image. I've searched on the internet and found out that people have done it by putting CSS filter property through javascript on Image to make it blur. But it can be removed by inspecting the page and I don't want that.
I want to generate a blurred version of image through javascript. I think I can do it with canvas but I never worked with canvas and any help will be highly appreciated (:
So, it depends. If you're worried about them removing it with developer tools, then the answer is probably "you can't".
The reason for this, is if you want to blur it with JavaScript, you need to send the unblurred image. And, if you send the unblurred image, they can easily scoop it out of the network tab, even if you never add it directly to the DOM. Anything you use as an input for JavaScript can be obtained by a clever enough user.
If you want the user to never be able to see the original, only the blurred, you'll have to blur it server-side.
If, for some weird reason, you're okay with that and still want to blur it in canvas, you'll need to pick and implement a blur algorithm for canvas. There are lots of different blur algorithms to choose from. Probably the most common one would be a Gaussian blur.
The algorithm isn't super insane, but it also isn't exactly super straightforward either, and I'd recommend using a library instead, such as this one: glur. I've not directly used that one, so can't vouch for it, but it has half a million downloads a week on NPM, so probably pretty solid.
Simple filters
You can apply a blur via the canvas using ctx.filter. CanvasRenderingContext2D.filter will accept a (limited set of) filters defined as strings. Eg ctx.filter = "blur(10px)";
See ctx.filter for set of filters you can use directly.
Example
Example uses CanvasRenderingContext2D.filter to blur image over time.
const img = new Image;
img.src = "https://i.stack.imgur.com/C7qq2.png?s=256&g=1";
img.addEventListener("load", () => requestAnimationFrame(uodate));
function drawImageBlur(img, blurAmount) {
const ctx = can.getContext("2d");
ctx.clearRect(0,0,128,128);
ctx.filter = "blur(" + blurAmount+ "px)";
ctx.drawImage(img, 128 - img.naturalWidth * 0.5, 128 - img.naturalHeight * 0.5);
}
var frameCount = 0;
function uodate(time) {
if (frameCount++ % 10 === 0) { // no point burning CPU cycles so only once every 10 frames
drawImageBlur(img, Math.sin(time / 1000) * 5 + 6);
}
requestAnimationFrame(uodate);
}
canvas {border: 1px solid black;}
<canvas id="can" width="256" height="256"></canvas>
There is no way to protect the image from inspection if you apply the image blur on the client (no matter what method you use). If you want to obfuscate (blur) the image it must be done on the server.
In my code I am loading images to canvas element. Then I need to drag, resize, rotate and skew it. I managed to implement both dragging and resizing. How can I implement skew using mouse on this code? I read a helpful article on this subject (http://www.subshell.com/en/subshell/blog/image-manipulation-html5-canvas102.html). I found fabricjs plugin, but it work only one image and without drag. For example: http://fabricjs.com/matrix-transformation/ .
If you will use the transform function:
ctx.transform(1, 0.5, -0.5, 1.2, 30, 60);
This will transform all image objects assigned to the canvas element. I would like only the selected image.
My code:
https://jsfiddle.net/sjLnqk5d/2/
Here's an updated fiddle that allows you to skew any image individually by pressing Shift when clicking one of the corner handles. You may need to tweak it a little bit to have the movements appear a bit more intuitive.
The trick is indeed in using ctx.save() and ctx.restore() around the ctx.transform() call, which makes sure that the transformation (and any other property changes) only applies between the save and restore.
Here are the key changes:
Shape.prototype.draw:
...
var skewX = this.skewX;
var skewY = this.skewY;
imgNew.onload = function(){
ctx.save();
ctx.transform(1, skewX/100, skewY/100, 1, 0, 0);
ctx.drawImage(imgNew, locx, locy, width, height);
ctx.restore();
}
I have been searching on the internet for a simple way to blur a canvas image. I thought it would be easy to find information about how to program the gaussian blur function but every time I found something, it always included a lot of unneeded functions like animation and so on. All I want is to take an image -> draw it in canvas -> blur image-> output image to data -> apply the data to a div element -> then delete the canvas element.
I saw this one about motion blur: Better canvas motion blur Which didn't require that much code. How do I do something similar but in gaussian blur instead of motion blur?
In the example you posted, the HTML5 globalAlpha property of the target image is changed to change its opacity, and then the image is painted 10 times on a different vertical point to create the illusion of a motion blur.
For a normal Gaussian blur, you can use the regular CSS3 filter / feGaussianBlur attributes. Check here for an example:
http://css-plus.com/2012/03/gaussian-blur/
In particular, the section named "SVG blur filter applied to a SVG image element"
There are more techniques to do this, including Javascript plugins like the following:
http://blurjs.com/
http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
However, the CSS3 filter / feGaussianBlur attributes should be the simplest to use, for your needs.
Try this:
blur = function (canvasId) {
var c = document.getElementById(canvasId);
var ctx = c.getContext("2d");
ctx.globalAlpha = 0.3;
var offset = 3;
for (var i=1; i<=8; i+=1) {
ctx.drawImage(c, offset, 0, c.width - offset, c.height, 0, 0, c.width-offset, c.height);
ctx.drawImage(c, 0, offset, c.width, c.height - offset, 0, 0,c.width, c.height-offset);
}
};
blur("myCanvas");
I'm trying to accomplish an effect similar to what you might see on the cartoon Chowder (example link) , where shapes serve as masking layers for a texture underneath that stays static. I've begun playing around with this idea by creating a render loop that clears the canvas, saves it's state, then draws a rectangular clipping region, followed by drawing the background texture that occupies the entire width and height of the canvas.
Here's the draw function:
function draw()
{
context.clearRect(0,0, 640, 480);
context.save();
x += velocityX;
y += velocityY;
context.rect(x, y, 40, 40);
context.clip();
context.drawImage(image, 0,0, 640, 480);
context.restore();
}
Basically it just runs at 60 frames per second, updating the position of the rectangle and clipping a background image inside the clipping region. (I know the code isn't structured perfectly, but I was just experimenting to see if this effect was even possible on the canvas).
http://jsfiddle.net/JERje/86/
The problem I seem to be having is that the clipping area from the previous iteration of the loop hangs around creating the weird effect that you see in the fiddle above. I've tried reordering everything in the draw() step of the loop, but the only thing that seems to work is the canvas.width = canvas.width trick for clearing the screen. I'd like to avoid this method of clearing the screen, since it doesn't seem to work in IE, and it also destroys the canvas state. clearRect() should work to clear the screen. What am I doing wrong?
You're using the same HTML5 Canvas paperback I am aren't you.
If you set up an adhoc canvas as I did on your jsfiddle like so:
var newCanvas = document.createElement('canvas');
newCanvas.getContext("2d").drawImage(image,0,0);
A function such as this would be able to hack a section out of that canvas:
context.putImageData(newCanvas.getContext("2d").getImageData(x,y,40,40),x,y);
Thus giving you the chowder effect. Good show man, good luck. Pst me if it doesn't work
EDIT: However this solution will ignore some context scaling transformations. Just be smart about how you handle scale on your own (and you really should be anyways if you want the true "chowder" effect)
So, feel pretty dumb about this, but apparently when you call rect() you also have to make sure to call closePath afterwards in order to close the clipping area. Glad I figured it out finally, now on to adding multiple layers!
Here's the working fiddle: http://jsfiddle.net/JERje/129/
I am running firefox 3.5.6.
I want to display an image on a canvas and draw a couple lines on it. It needs to display properly in firefox and internet explorer (using excanvas).
Here is what I am getting:
The top image is what I see in IE8, the bottom is what I see in firefox.
IE seems to be a bit messed up as far as the canvas is the wrong size but firefox is going crazy! What gives with this aspect ratio? Why does the second half of my arc not appear?
Also, some times firefox just flat out doesn't show anything.
Here is my code by the way.
Aspect ratio problem
If you don't set a width on the canvas element, it defaults to 300x150. In your CSS, you set the style to 94x120, so it scales the image to that size. To fix it, you need to either set the width and height in the HTML, or with JavaScript.
In HTML:
<canvas id="c" width="94" height="120">Ugh, this just ain't gonna work</canvas>
In JavaScript (with jQuery):
$('canvas').attr('width', '94').attr('height', '120');
Internet Explorer's incorrect size
Adding the size to the canvas element should fix this problem too. Since IE is using VML instead of a canvas to render the image, the CSS rule for canvas won't apply. excanvas should see the specified size and apply it in IE.
Missing the second half of the arc
The simpleArc function doesn't work in Firefox when the amplitude is negative. The problem is that a negative amplitude results in a negative radius for the arc, which is illegal according to the canvas spec. It should actually throw an INDEX_SIZE_ERR exception, but Firefox just seems to ignore the call.
There are two possible solutions (basically; there are several ways you could accomplish either): when you pass a negative amplitude, either calculate the parameters for the arc taking into account the negative radius (with a different center point and angles, etc.), or change the sign and use transformations to rotate the arc. I implemented the second solution like this:
ctx.simpleArc = function(x,y, length, amplitude) {
var rotate = false;
// Check whether we need to rotate the image
if (amplitude < 0) {
rotate = true;
amplitude = -amplitude;
}
var radius = amplitude/2+ length*length/(8*amplitude);
var outerAngle = Math.asin((radius-amplitude)/radius);
var innerAngle = Math.PI - 2*outerAngle;
// The translate/rotate/translate steps could be combined into one matrix
// transformation, but I think this is clearer and less error-prone.
if (rotate) {
this.save(); // So we can easily undo the transformation
this.translate(x + length, y);
this.rotate(Math.PI);
this.translate(-length, -y);
}
this.arc(x+length/2, y+(radius-amplitude), radius, -(outerAngle+innerAngle), -outerAngle, false);
// Reset the transformation matrix to its original value
if (rotate) {
this.restore();
}
return this;
}
Firefox not showing anything
In your code, you create the image and set the source, but it may not be loaded before the rest of the code get's executed. The image loads asynchronously, and when you draw the image onto the canvas, it doesn't wait for it to finish. You will need to call the code that uses the image from an onload event.
var img = $('<img>');
img[0].onload = function() {
ctx.drawImage(img[0], 0, 0);
ctx.strokeStyle = "blue";
ctx.simpleStroke(function(ctx) { ctx.simpleArc(0, 70, img_w/2, 3)});
ctx.simpleStroke(function(ctx) { ctx.simpleArc(img_w / 2, 70, img_w/2, -3)});
};
// I moved this so it happens after you set the `onload` event, because I
// think IE won't call `onload` if it happens to already be loaded.
img.attr('src', 'shortcylinder.png');
You could also pre-load all the images you will need instead of creating them when you need them. You would still need to prevent the code from running until all the images are loaded.
I've recently noticed that using style to define width & height for canvas elements caused an issue like this. Taking from an earlier example
This works in FF 9.0.1 Mac
<canvas id="c" width="94" height="120">Ugh, this just ain't gonna work</canvas>
vs.
This had similar display issues as your example, in FF 9.0.1 Mac
<canvas id="c" style="width:94;height:120;">Ugh, this just ain't gonna work</canvas>
Maybe that's it?