Rotating Image on Canvas - javascript

In my web app I am allowing users to choose images. If the height of the image is greater than the width then I rotate the image by 270 degrees.
I am confuse about what should be the ideal size for the rotated image as I would be saving that rotated image later on.
For example if a user upload a image with low resolution what should be the size there and what if the user uploads an image with a high revolution what would be the size than?
I don't want the pixels to be distorted. Any good library to rotate image on the client side? Or any algorithm which can help me?

You could try the naive canvas approach like this:
Basically you'll be drawing the image on a canvas, rotated, then saving the canvas to a dataUrl
var context = canvas.getContext('2d');
//save the context
//pushes a Matrix on the transformation stack
context.save();
context.translate(x, y); //where to put image (in the canvas)
context.rotate(angle); //angle in degrees (i think...)
context.scale(scale); //optional scale
//rotate around center of image
context.drawImage(bitmap, -image.width / 2, -image.height / 2);
//or rotate around top left corner of image
context.drawImage(image, 0, 0);
//restore the canvas
//pop a matrix off the transformation stack
context.restore();
//now save the canvas to a data url for download or to display in an image object / tag
var data = canvas.toDataUrl();
References:
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations
https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement
http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/

you can use Blob object approach. Convert the image to blob objects and you can play with it. I cant help with code coz am not much aware of blobs. Please do more research on blobs and you can achieve what you want to do using Blobs.

Related

Attempting to create a single map image from tiles using canvas element

I have a bunch of png map tiles that I am trying to stitch together on a canvas element.
jsFiddle
I am making a 10x10 tile with a counter from 0 to 99 (id) to keep track of where I'm up to. This is the line that plots the image:
ctx.drawImage(this, id%10*imgWidth, Math.floor(id/10)*imgHeight, imgWidth, imgHeight);
Where id is some number from 0 to 99, imgWidth is the width of each tile and imgHeight is the height of each tile.
I am reasonably confident that should work, but it appears to just plot one stretched tile on the canvas instead of all 100. When I check the console for what was loaded, the images appear to be the correct shape and contents for each tile. The just don't seem to have been placed on the canvas. Does anyone have any ideas?
One reason to not use jQuery with canvas:
$('canvas').width(imgWidth*10).height(imgHeight*10);
:) as this refers to the element size, not the bitmap. I would suggest using instead:
myCanvas.width = imgWidth*10;
myCanvas.height = imgHeight*10;
Modified fiddle

Rotate drawing on canvas

I have a simple task - I need to draw one rectangle, rotate and copy it and clone its rotated version. I try to do it like so:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
//1. rotate canvas
ctx.rotate(-30 * Math.PI / 180);
ctx.rect(10, 60, 80, 40);
ctx.stroke();
//2. copy rotated rectangle
var img = ctx.getImageData(0, 0, 140, 140);
//3. rotate back
ctx.rotate(30 * Math.PI / 180);
//4. draw rotated version of the rectangle
ctx.putImageData(img, 80, 100);
The idea is very simple. At first step I draw a rectangle, at the second step I rotate my canvas and do what I think is a snapshot (or create a copy of my rotated rectangle), at the third step I rotate my canvas back (so my rotated rectangle must not be rotated any longer) and at the final step I add a new object to the canvas - the copy of the rotated rectangle. But this is what I get:
Whereas I expected to get this picture:
What am I doing wrong and how can I get the desired result?
"putImageData is not affected by the transformation matrix"
See here: putImageData() on rotated canvas work incorrect
Instead, if you want a complex image to be copied into memory, and then repeatedly drawn on the screen at different angles, you might consider using a temporary canvas. This post gives a good example:
How to rotate the existing content of HTML5 canvas?
If you need to create multiple image sprites, and creating multiple canvases won't do, consider drawing your sprite to an appropriately sized temporary canvas, and then convert the contents of the temporary canvas to an image using canvas.toDataUrl
The post gives a nice example:
https://davidwalsh.name/convert-canvas-image

Rotate image by 90 degrees on HTML5 Canvas

I am having trouble rotating an image using an HTML5 canvas. I suppose that I just have the math wrong, and would appreciate any help in getting this right.
On a mobile device I am capturing a user signature on a 150px by 558px canvas. I am than attempting to create a 558px by 150px image that is just the captured signature rotated 90 degrees. Below is a snippet of the code I've currently come up with. As you can likely surmise, I do not have a good grip on the math going into this. I believe I have the procedure correct, just not the numbers.
What I'm trying to do is:
1) set the center of the canvas to the middle, offsetting by the height and width of my image
2) rotate the canvas by 90 degrees
3) draw the image
4) translate the canvas back.
EDIT: Here's a JSFiddle: http://jsfiddle.net/x9FyK/
var $signature = $("#signature");
var signatureData = $signature.jSignature("getData");
console.log(signatureData);
var img= new Image();
img.onload = function() {
var rotationCanvas = document.createElement('canvas');
rotationCanvas.width = img.height;
rotationCanvas.height = img.width;
var context = rotationCanvas.getContext("2d");
context.translate((rotationCanvas.width/2) - (img.width/2), -(rotationCanvas.height/2) - img.height/4);
context.rotate(Math.PI/2);
context.drawImage(img,0,0);
context.translate(-((rotationCanvas.width/2) - (img.width/2)), -(-(rotationCanvas.height/2) - img.height/4));
var rotatedData = rotationCanvas.toDataURL();
...Handling rotated data here
};
img.src = signatureData;
If I can provide any more information, please let me know.
Thanks in advance for your help,
There are several ways of resetting a transformed (translated+rotated) canvas back to its original state.
Low-Pointer's answer is using context.save to save the context in is original un-transformed state and using context.restore to restore the context to its original state after the drawing is done.
The other way it to undo your transforms in the reverse order that they were performed.
Also, note that context.translate will actually move the canvas origin to the center of the canvas. Since images are drawn from their top-left (not their center), you must offset drawImage by half the image width and height if you want the image centered in the canvas.
Here's and example: http://jsfiddle.net/m1erickson/EQx8V/
// translate to center-canvas
// the origin [0,0] is now center-canvas
ctx.translate(canvas.width/2,canvas.height/2);
// roate the canvas by +90% (==Math.PI/2)
ctx.rotate(Math.PI/2);
// draw the signature
// since images draw from top-left offset the draw by 1/2 width & height
ctx.drawImage(img,-img.width/2,-img.height/2);
// un-rotate the canvas by -90% (== -Math.PI/2)
ctx.rotate(-Math.PI/2);
// un-translate the canvas back to origin==top-left canvas
ctx.translate(-canvas.width/2,-canvas.height/2);
// testing...just draw a rect top-left
ctx.fillRect(0,0,25,10);
this will surely help you >>HTML5 Canvas Rotate Image :)
use some SEPARATE js function for drawing your canvas :
function drawRotated(degrees){
contex_var.clearRect(0,0,canvas.width,canvas.height);
contex_var.save();
contex_var(canvas.width/2,canvas.height/2);
contex_var.rotate(degrees*Math.PI/180);
contex_var.drawImage(image,-image.width/2,-image.width/2);
contex_var.restore();
}
Suppy some angle to any buttonclick function:
$("#clockwise").click(function(){
angleInDegrees+=30;
drawRotated(angleInDegrees);
});

Saving a canvas drawing larger than the physical screen

I'm dynamically drawing a floorplan through canvas which you can scroll through up/down left/right but I would like to save the whole image of the floorplan for other uses. I know I can scale the floorplan down and capture the image but I need it to be in a higher resolution than the actual screen I'm capturing it on.
I'm currently using FileSaver.js to save the canvas as a bitmap because it's super easy.
Is this possible?
It's hard to tell without more information, but you can create a larger canvas (of the size you need it to be) and let it hidden. Then when you want to capture, you re-draw everything into that canvas and save your picture from it instead of the one that is displayed.
So you don't need to save the canvas, but the image.
I don't know your FileSaver.js, but if it cannot save an image directly,
putting the image inside a new canvas is easy :
function getCanvasFromImage(img) {
var cv = document.createElement('canvas');
cv.width = img.width; cv.height = img.height;
cv.getContext('2d').putImage(img, 0, 0);
return cv;
}

canvas - layer small image on larger background image, merge to single canvas pixel data

How do I merge a smaller image on top of a larger background image on one canvas. The smaller image will move around. So I will need to keep reference of the original background pixel data, so that the each frame the canvas can be redrawn, with the overlay in its new position.
BgImage: 1280 x 400, overlayImage: 320 x 400, overlayOffsetX: mouseX
I think it is common to draw whole scene each time you want to change something, so:
context.drawImage(bgImage, 0, 0);
context.drawImage(overlayImage, overlayOffsetX, 0);
UPDATE
You could manually compose image data of two images with making copy of background image data
or
do something easier, probably faster. You could create new canvas element (without attaching to the document) which would store image data in easy to manage form. putImageData is good if you want to place rectangular image into the canvas. But if you want to put image with transparency, additional canvas will help. See if example below is satisfying you.
// preparation of canvas containing data of overlayImage
var OVERLAY_IMAGE_WIDTH = 320;
var OVERLAY_IMAGE_Height = 400;
var overlayImageCanvas = document.createElement('canvas');
overlayImageCanvas.width = OVERLAY_IMAGE_WIDTH;
overlayImageCanvas.height = OVERLAY_IMAGE_HEIGHT;
overlayImageCanvas.getContext('2d').putImageData(overlayImage, 0, 0);
// drawing scene, execute this block every time overlayOffsetX has changed
context.putImageData(bgImage, 0, 0);
context.drawImage(overlayImageCanvas, overlayOffsetX, 0);

Categories

Resources