If you click Run code snippet in this link, it shows a cool usage of <canvas> where you can "cut-out" part of the image (just drag your mouse on the image to "cut"). I'm just curious if there is any way to save the resulting "cut-out" part of the image, as a transparent PNG (i.e. everything that is white in the canvas would be transparent).
If anyone can point me in the right direction (or tell me it's not doable), I'd appreciate it.
Yes, there is a way. Use canvas context.getImageData to get image raw data-array. Do with it(raw data) what you need(make transparent any pixel you need), and then use context.putImageData to render data on canvas. Then use var data = canvas.toDataURL("image/png") to get image data. And then you can do so: image.src = data;
Use this link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData for more info
Here's a quick tour showing how to crop & save a user-dragged cutout of an image:
Draw the image on the canvas.
Listen to mouse events and let the user define the region they want to cut out by continuously connecting new lines to the current mouse position.
Save every mouse point from #2 in an array.
When the user has finished defining their cutout region:
Clear the canvas.
Draw and fill the cutout area using the saved points in the arry.
Set context.globalCompositeOperation='source-in'. This mode will cause any new drawings to appear only where the newly drawn pixels and the existing pixels overlap and every thing else is made transparent. In common terms: New pixels will be "clipped" into the user defined cutout and new pixels will not appear outside the cutout.
Redraw the image.
The result is the second drawing of the image will appear only inside the user defined cutout. Everything else will be transparent.
Finally, you can use var url=canvasElement.toDataURL to save the cropped canvas image into a .png dataURL. If you then want an actual image from this dataURL you can var img=new Image() and set the img.src=url.
Related
I'm using Guillotine JS to manipulate the image rotation, scale, positions, x,y, when user has finish making changes, I use html2canvas to get the final image generated inside a div, in this case my div has a class .frame, so, when user zoom in or out move left right up, down, I do this:
html2canvas(target, {
onrendered: function(canvas)
{
var data = canvas.toDataURL("image/png");
//console.log(data);
var imgdata = data.replace(/^data:image\/(png|jpg);base64,/, "");
}
})
I have skip a bunch of code this is the only thing I use, with that I get a 64base code for the image inside my div up to this point everything is ok, the generated image is exactly what is need.
The problem is when rotation is apply to the image, for testing I'm using an image with: width: 1036, height: 615px inside a div with: width:676, height:459px.
This is the generated images
Same as before, different area
Same image but this time it has a rotation 180'
same image, rotation 90'
As you can see every time a rotation is use, the result are wrong.
How can I fix that?
I have used Imagemagick to rote and crop the image using guillotine data, the problem here is that the scale is all messup image width * scale only gives 1 x 1px image as a final result, if I hardcode the width and height the result is the same, so I'd love to find a way to fix the rotation with html2canvas.
I'd like to know if there is some way in Kinetic to have an image merged with another image on a lower layer, creating a kind of crop effect based on the shape of the "cropping" image.
The image must have a transparent background as a result, which is the main source of difficulty for me. I would otherwise just have used a mask with dragging turned off... I've made a diagram to explain what I want a bit better. Any suggestions welcome.
diagram
I've also made a quick jsfiddle, where I would like the contents of the image to be displayed inside the box. I feel like one layer is the way to go on this one.
You can use an offscreen Canvas element plus compositing to create your clipped image for use by your Kinetic.Image. Note that the offscreen canvas can be used as an image source for your Kinetic.Image.
Example code and a Demo: http://jsfiddle.net/m1erickson/ks1xxqfL/
var canvas=document.createElement('canvas');
var ctx=canvas.getContext('2d');
canvas.width=background.width;
canvas.height=background.height;
ctx.drawImage(mask,0,0,mask.width*2.25,mask.height*2.25);
ctx.globalCompositeOperation='source-in';
ctx.drawImage(background,0,0);
var support=new Kinetic.Image({
draggable:true,
image:canvas,
});
layer.add(support);
layer.draw();
Illustrations
Left: the background image,
Center: the image to be used as a clipping mask
Right: the background clipped by the mask (mask was scaled by 2.25X)
I have applied dragging (built in ability) on my group which consists of image object and 4 anchor objects (shapes).
When I move group all works ok, but when I want to save that image. Image gets cropped as Image(group) is moved away of (0,0) position. If I load image and save it when it is on (0,0) position get full image in file, but if dragged it away from 0,0 than my image gets cropped progressively, when I save it.
I observed what toDataURL() is returning and really further I go from 0,0 string gets shorter from toDataURL()
Please can somebody help me.
Thx
If you drag the group, you must define the x,y,width,height properties of toDataURL:
A Demo: http://jsfiddle.net/m1erickson/Kr3t2/
var url=group.toDataURL({
x:group.x(),
y:group.y(),
width:group.getWidth(),
height:group.getHeight()
});
I have a canvas <canvas></canvas> that displays a graphic of an unclean window. I need to be able to 'clean' the window with my cursor, displaying another image behind it. Just as this website uses their brushes: http://mudcu.be/sketchpad/ but rather than adding to the page, I need to remove content to display the image behind it.
Here's an example of the before and after 'rubbing out':
http://www.titaniumwebdesigns.com/images/forums/before.png http://www.titaniumwebdesigns.com/images/forums/after.png
See this complete DEMO
globalCompositeOperation is one of the most nice features in canvas api.
To achieve the desired effect, I use multiple canvas layers and globalCompositeOperation.
In this solution we have 3 layers:
Layer 1 - bottom Layer 2 - middle
Layer 3 - top
Middle and Top layers are static and only the middle layer is dynamically cleared using globalCompositeOperation.
middleCtx.globalCompositeOperation = "xor";
With globalCompositeOperation = "xor", the brush is drawn over the layer and clears the portion of canvas where it was drawn.
The final result is:
UPDATE:
To verify if the window is fully cleaned I create a hidden canvas with the same size of the others layers and drawn a black rectangle on it. When dragging the mouse over the canvas the layer 2 (middle) is cleared with a circle with transparent gradient color and now we also draw over the hidden canvas a circle with white color (might be any color different of black).
So on, we just verify the pixels of the hidden canvas and if there is no black pixels, the window is cleaned.
To get the image data we need to use something like:
imageData = context.getImageData(x, y, width, height)
and then get the pixels from the image data:
pixels = imageData.data;
The requestAnimationFrame routine is used for performance reason, because getImageData might be slow. The major change in the code is put the brush action inside an animation frame when dragging the mouse instead of do that action in each mouse move event. This allows the processor to have more time to do the pixel data verification.
Here is the modified fiddle with pixel data verification and an alert when the window is cleaned:
jsFiddle link
If you have a canvas where you have drawn a blurred image into it once, you should be able to create that effect by creating a "brush" image (an image containing a semi-transparent circle, with soft edges), and then draw that image in the canvas at the mouse coordinate using:
canvasContext.globalCompositeOperation = "destination-out";
https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
As soon as you have drawn the blurred image to the canvas, you just need to call the line above once and all drawn images after will use the specified composite operation.
I would like to export my canvas onto a PDF and only render the elements added to the canvas. For example:
I have this canvas, with a background-image set to it.
http://i49.tinypic.com/n7lv.png
This is my result when I render it to PDF (using Bytescout library)
http://i50.tinypic.com/346ud7m.png
This is how I want it to end up as:
http://i50.tinypic.com/2q1s9hv.png
Meaning, I want it to end up with no rounded corners, without the background image. The canvas is done using the fabric framework. My idea is to get all the elements added to the canvas, except background image, then render the PDF from there. Any guidelines? Is that the way to go?
You simply redraw the entire scene, omitting the parts you don't want to write to a PDF.
If you don't feel like keeping track of everything to redraw, then create a second, in-memory canvas (document.createElement('canvas')) and do every drawing operation to that canvas instead of your normal one, then draw that canvas onto your normal one as the user edits instead of drawing directly onto your normal canvas.
The old way:
// First you round the corners permanently by making a clipping region:
ctx.roundedRect(etc)
ctx.clip();
//then a user draws something onto normal canvas, like an image
ctx.drawImage(myImage, 0, 0);
The new way:
// make a hidden canvas:
var hiddenCanvas = document.createElement('canvas');
var hCtx = hiddenCanvas.getContext('2d');
// First you round the corners permanently by making a clipping region:
ctx.roundedRect(etc)
ctx.clip();
//then a user draws something onto HIDDEN canvas, like an image
// This image never gets its corners cut
hCtx.drawImage(myImage, 0, 0);
// Then you draw the hidden canvas onto your normal one:
ctx.drawImage(hiddenCanvas, 0, 0);
When its time to print, you use your hidden canvas, which does not have a background image and does not have clipped corners.