Scale image to fit on canvas, while maintaining aspect ratio. - javascript

I'm trying to figure out how to render an image on a canvas, changing the canvas zoom to best fit the image (to a mimum size of 50% zoom), and allowing the user to pan around the canvas to see the remainder of the image, if it didn't all fit on the screen.
I've been writing an Image cropper and I've noticed that the two problems I'm running into are that
When the Image is too big it's cut off of the canvas.
When the Image is too big it takes up the entire screen.
By limiting the size of the canvas and changing the zoom of the image, I should be able reduce these issues. In the event an image is still too large, you can pan around the screen. Here is an image example of what I'm looking for
Where the RED is the Canvas element, and the PINK is the Image. (Being displayed on the Canvas, and sticking out on both sides). So the user should be able to pan left, or pan right and see the parts of the image that don't fit on the screen.

Related

toDataURL() small screens, small saved image

I have created a web application which uses an HTML5 canvas element to allow users to draw in various shapes, colors, line widths. They can also upload an image, have it drawn onto the canvas and then draw on top of that, as a way to annotate their images.
My challenge is that I am using .toDataURL() to get the entire contents of the canvas saved as an image. As I understand, though, this can only capture the size of the canvas. On smaller devices (phones), the image which is saved, ends up quite small dimensions. Here's what I am doing to get what is on the canvas:
var image = document.getElementById("drawingCanvas").toDataURL("image/jpeg", 1.0);
image = image.replace('data:image/jpeg;base64,', '').replace('data:image/png;base64,', '');
Is there some way to set up my canvas to be able to save larger images, even if the size of the canvas is quite small, due to the device?
Sure...
Save the commands used to create the client's drawing.
Create a larger in-memory canvas with document.createElement.
drawImage a full-sized image to the canvas.
context.scale the canvas.
Re-issue the drawing commands.
Export the enlarged canvas with .toDataURL.
Thanks to context.scale you don't have to change any of the coordinates of the drawing commands.
...and alternatively...
You could eliminate step#1 if you're willing to downgrade the drawings to allow some "jaggies". Do this by using CSS to overlay a canvas on top of the client's img. That way the client's drawings are already isolated on the original canvas. Then your procedure simplifies to:
Create a larger in-memory canvas with document.createElement. Make sure the larger canvas has the same aspect ratio as the original canvas.
drawImage a full-sized image to the canvas.
drawImage the original smaller canvas to the larger canvas. You can use the extended version of drawImage to simultaneously scale the client's drawings: context.drawImage(originalCanvas, 0, 0, originalCanvas.width, originalCanvas.height, 0, 0, largerCanvas.width, largerCanvas.height). Yes, the image source for drawImage can be another canvas. ;-)
Export the enlarged canvas with .toDataURL.

HTML5 canvas and scrolling

I have a canvas element of size 1024x768 where I draw a very large image, let's just say with width >> 1024 and height >> 768. The image can be scrolled with normal scrollbars to be seen entirely.
Users can click onto the canvas to add vertices to a polygon: each time a vertex is added, a line from the new vertex to the mouse cursor is drawn.
Each mouse movement onto the canvas updates the canvas in order to redraw such line from the vertex to the new mouse cursor position.
Being the image VERY large, redrawing is very slow, so I'd like to just redraw the currently visible chunk of image or, even better, the "sub-chunk" that is affected by this line.
The problem is: how do I detect the current topLeft and bottomRight of the visible part of the context according to how much the user scrolled the image? Basically I'd like to add support for a custom viewport, but I can't seem to exploit the scolling information to determine the boundingBox of the chunk to crop from the original image.
I actually have a canvasDiv container, which is the real scrollable element, not the canvas itself.
This means your canvas is the full size and you're using the container div as a sort of a "frame". That's really bad as canvas pixels are quite expensive, especially if you're not even using them (they're out of the viewport).
The best approach here is to set the canvas size to the container size and use the drawImage function to control the scrolling. The original image would be places either on an offscreen canvas or an image element. I can guarantee you a much better performance this way.
You'll lose the scrollbars, that's the downside.
I'm assuming you create the scrollbars by having a larger canvas element contained inside a smaller div.
Instead, you can mimic this setup by:
Having a canvas the size of your container div.
Add 2 input type=range controls to act as vertical & horizontal scrollbars (or grab a jqueryUI scrollbar plugin if you want to be fancy).
Then you can use the clipping version of context.drawImage to draw only the portion of the image specified by the range controls. The clipping version of drawImage looks like this: drawImage(myLargeImage, clipX,clipY,clipWidth,clipHeight, 0,0,canvas.width,canvas.height)

how to use transparent effect for only a part of the image

I am not sure if it is possible. But let's say there are two images, one over another. Then I will have a circle size 100px around my cursor. So when I move the cursor over the image, it shows part of image that is under the front image. So the back image is hidden and visible only if the circle size 100px is over some part of it.
Unfortunately I have no code as I am not sure if it is possible to create.
However, any idea about it?
I would try actually stacking the hidden image above the visible one, then use HTML5's canvas to track your mouse cursor, clip a circular area underneath your cursor, then draw your image above it. This gives the illusion that you're "revealing" an underlying image, when in fact you're really revealing a small portion of an image stacked on top. Repeat this any time the user moves his/her cursor.
Here are some resources you might find useful in coding this:
HTML5 Canvas Clipping Region Tutorial
HTML5 Canvas Mouse Coordinates
Stack Overflow: clearing circular regions from HTML5 Canvas

Hints to speed up my canvas app

This is about WEB development, Canvas, HTML5.
I'm developping a paint application with HTML5 Canvas and JQuery. You can draw several layers, and you got a dynamic zoom with a magnifying glass effect.
The architecture is multiple canvas :
background :
canvas-bg
layers :
layer0
layer1
layer2
...
layerN
tools :
ghost (to display a "ghost" line when the user want to draw a line. Releasing mouse confirm the draw)
magnify-layer
My problem is the zoom. To get the effect I want I redraw ALL LAYERS on the magnify-layer. Of course, when you are drawing a 2000*2000 picture, it is VERY slow. Moreoften, you can move the magnify-glass to zoom everywhere, and the redraw is recall on MouseMoveEvent.
To get it faster I only draw the little area under the glass (instead of entire layer). But it's still slow. How can I speed up know ?
illustration : http://imgur.com/hAtYsZi
You can see in the black circle the area is zoomed.
I used this code to start :
Démo : http://www.script-tutorials.com/demos/167/index.html
Try this...it might help.
I'm guessing you're doing traditional "magnifying": you're displaying at reduced resolution and then "magnifying" at full resolution.
So, when the user selects the magnifier tool, "flatten" all your layers onto another canvas.
Then cache the flat canvas to an image at 1/2 resolution. This becomes your unmagnified background.
Finally do your magnifying trick: Grabbing the appropriate pixels from the flattened canvas and show them in a floating magnifier.
Yes, there is some overhead+time in flattening your image, but that might be offset by the time it takes the user to select and position the magnifier.

Canvas drawImage with large images

What I am trying to make is some kind of scrollable viewport in which a really large image is loaded (as in 10.000 x 10.000 pixels or more) and I should be able to draw some lines / shapes on this image.
There are two methods I can think of to draw the image / allowing the shapes to be drawn:
Using an tag to draw the image and draw a canvas the size of the image above it.
Using the drawImage() method to draw the image and just use a canvas.
I have tried both cases but when I load an image (in the img tag or using the javascript Image() object) it consumes about 500MB of memory.
I am wondering if there is a more efficient way to accomplish this.
Never ever make a user download an image that size unless you absolutely have to.
Make 100 smaller tiles (or thereabouts) of the image and draw the tiles to the Canvas, only drawing the tiles that can be seen at the current time (like google maps, etc do).

Categories

Resources