views:

55

answers:

1

I am building a firefox plugin which allows users to draw any arbitrary figure on an object and save it as an image (png file).

var $ = getJQueryOb();
var canvas = '<canvas id="canvas" width="1024" height="1024" style="position:absolute; top:0px; left:0px;"></canvas>';
var currentWindow = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var mainDoc = currentWindow.getBrowser().contentDocument;
var cObj = $(canvas).appendTo(mainDoc.body);
$(cObj).bind('mousemove', handlePenDraw);

Using this I can draw on the canvas. However, when I save the image, I do not want the full canvas to be saved - rather just the 'bounding rectangle' around the image that was created to be saved.

Is there any way I can acheive this. What I am currently doing is going to save the canvas as it is:

var $ = getJQueryOb();
var canvas = $('#canvas')[0];
var dURL = canvas.toDataURL("image/png");
saveToFile(dURL, "image-file.png");
+1  A: 

You could store the top left and bottom right coords that have been drawn on in your handlePenDraw method then retrieve the area that has been drawn on using the getImageData method.

Then put the imageData you've retrieved onto a new canvas that is only as big as the area drawn on to and then save the new canvas.

  • EDIT: I've now created a demo that does the above, except it doesn't save the new canvas, but just appends it to a div - http://jsfiddle.net/SMh3N/12/

Here's some rough untested code:

// Set these with these in your handlePenDraw method.
var topLeftPoint, bottomRightPoint;
var width = bottomRightPoint.x - topLeftPoint.x;
var height = bottomRightPoint.y - topLeftPoint.y;

// Retrieve the area of canvas drawn on.
var imageData = context.getImageData(topLeftPoint.x, topLeftPoint.y, width, height);

// Create a new canvas and put the retrieve image data on it
var newCanvas = document.createElement("canvas");
newCanvas.width = width;
newCanvas.height = height;

newCanvas.getContext("2d").putImageData(imageData, 0, 0);

// Now call save to file with your new canvas
var dURL = newCanvas.toDataURL("image/png");
saveToFile(dURL, "image-file.png");
Castrohenge
Wow! thanks a lot! getImageData() is the func I was looking for!
Kapil
@Kieranmaine Your solution is working well. However, I have a followup question. I notice that the putImageData() method is taking a bit longer time to add the image to the canvas. Instead, is there a way of extracting dataURL from the imageData itself? That way I would be able to reduce the time taken to make the image. Any ideas? I would be fine constructing the base64 string manually if it is permissible.
Kapil
I guess you could try converting the ImageData into a base64 string, although that could take longer than using putImageData and getDataURL.
Castrohenge