Using HTML5 canvas with SVG - html

I"m developing a diagramming application in HTML5/JavaScript. All drawing is done with SVG, using Raphael or qooxdoo SVG (not settled yet). The drawing area should use custom background image. The image is too big to be downloaded (several megabytes for 2560x1600 Retina resolution), that's why I construct it on the fly, composing it from tiles and applying bitmap effects. For that, I use HTML5 canvas. After that, the resulting background image has to be made accessible from SVG. To achieve that, I export a data URI from the canvas, and use <image xlink:href="data:image/png;base64,..."/> inside SVG.
This works for simple examples, but I'm a bit concerned about memory usage in production. Given that the image takes 12MB in memory (2560 * 1600 *3 bytes ber pixel), how much additional memory will be used? I suppose that at least some megabytes will be allocated to store base64-encoded PNG-compressed representation as data URI, and another 12 megabytes will go to the buffer for the SVG <image> element.
I wonder if there is a method to short-circuit this and to avoid redundant image encoding-decoding?

You can go around the base64 part with canvas.toBlob(callback) and window.URL.createObjectURL(). Other than that I don't think there is a place for you to further limit memory usage.
https://developer.mozilla.org/en-US/docs/Web/API/window.URL.createObjectURL
The toBlob() method can be shimmed on some browsers: https://github.com/blueimp/JavaScript-Canvas-to-Blob

Related

Diagrams in SVG versus HTML5 Canvas

I want to start a project where I need to draw diagrams consisting of rounded rectangles connected with lines and a JavaScript action when I click some elements. This needs to work in all modern browsers.
Both SVG and HTML5 Canvas seem to be able to do this so I wonder what would be best.
Also I don't want to reinvent the wheel, so if there are libraries that do such things I would like to know; I took a look at Raphaël and some other JavaScript drawing libraries but they don't give all the functionality I need. In Google's API there is such a tool but it is very limited.
Use SVG because—as a retained-mode drawing API—you can attach event listeners directly to specific elements, and change properties of specific elements and have the page magically update. Further, as a vector-based format, it is resolution-independent.
HTML5 Canvas, by comparison, is a non-retained-mode (aka immediate-mode) drawing API; every pixel you draw is blended with all other pixels on the canvas, with no concept of the original shape. Further, as a raster-based format, you would need to do some extra work to get the drawing commands to adjust for different display sizes.
In general, you should use Canvas if and only if you need:
Direct setting of pixels (e.g. blurs, sparkly effects), or
Direct getting of pixels (e.g. reading a user's drawing to save as a PNG, sampling portions of the image to detect visual overlaps), or
massive number of 'objects' that won't move much or track individual events (SVG can be slow to redraw with thousands of objects).
Note also that you don't have to choose only one or the other. You can draw SVG onto canvas. You can include bitmaps (images) in SVG. You can even include HTML5 Canvas in SVG via <foreignElement>. You can have a single HTML page with multiple layered canvases and SVG elements with transparent backgrounds, intermingling the output of each.

Is there a practical limit to the number of canvas elements you can have on one page?

Is there a practical limit to the number of HTML5 canvas elements you can have on one page?
For example, is 500 individual canvases feasible for a modern browser on the average computer?
Each canvas consumes memory at least, not less than an image of the same size.
How big are those canvas, anyway?
Having 500 different images on the same page could slow down the PC, and if those images are scaled down via CSS (so you have additional CPU usage), the slowness is overwhelming (I already tested it).
quick test done:
Ive created 500 512x512 canvases, and the Windows memory usage was about 40MB. Not so much, really.
Now I should draw in each one via JS, maybe using them allocates much more memory.
-edit-
500 canvases, 512x512, in each one is drawn a triangle: http://jsfiddle.net/3U4hG/1/
Consumes about 0.5GB, about 1MB for each canvas, and considering that 512x512x4 (4 bytes per pixel) is 1MB, the memory usage can be easily determined.

HTML5 canvas image how can be saved in SVG or base 64 format?

can we export canvas image as svg or base 64 and then import it back again?
It's not easy, no. There is no direct method to export Canvas graphics to SVG - they are fundamentally different types of representation, Canvas 2D uses a raster display, like television images, and SVG stores the geometric shapes, which can be resized without degradation of quality.
The simple answer is if you need SVG output, don't use canvas, start with SVG
(the simpler SVG graphics library http://raphaeljs.com/ might be useful here).
The complex answer is - you could export to SVG if you record all the canvas operations you perform and have some way to recreate them with SVG, but, unless you have a restricted set of operations, that basically means you need to implement all canvas drawing functions and modes!
andrewmu gets a well-deserved point from me for the great answer to the question in its original form.
The amended question ("or base64") is easy to Google: canvas.toDataURL().

Decoding a GIF question

For a personal project I'm creating a static gif decoder. Everything works well so far, except I'm having trouble understanding one concept from the specification:
This block is REQUIRED for an image.
Exactly one Image Descriptor must
be present per image in the Data Stream. An unlimited number of images
may be present per Data Stream.
(Spec)
Unlimited images per data stream? There can be more than 1? I'm assuming they don't mean an animated GIF because in the same specification they state, that they don't recommend gif's be used for animation.
I've read a lot of other sites documenting the gif format and they all state something similar. Heres another link:
There might be an unlimited number of images present in a GIF.
Any ideas?
GIF87a does not allow animation, but enables multiple images in GIF.
The idea was to decompose (for better total compression ratio) large picture into several rectangular subpictures drawn on a common canvas initially filled with background color. Every subpicture has its own x, y, width, height and palette. For example, if you are drawing astronomic picture: Earth and Moon, these two objects may be represented as two small subpictures on common large black canvas. It is not an animation: both subpictures are visible simultaneously.
But this beautiful idea was not supported by software (browsers, picture viewers, etc.), probably due to such non-standard approach.
Since GIF89a these subpictures were transformed into animation frames.
There can be more than one image present in a GIF file. Yes, GIF files can perform crude animation, but it's usually not pretty.

sprites vs image slicing

I don't have much experience with the sprite approach to images (http://www.alistapart.com/articles/sprites). Anyone care to share some pros/cons of sprites vs. old-school slices?
The main advantage of sprites is that the browser has to request less pictures from the webserver. That reduces the number of HTTP requests and makes it possible to compress the parts of the design more effectively. These two points also represent the disadvantages of sliced images.
Here you can see some good examples how sprites improve the loading speed of web pages:
http://css-tricks.com/css-sprites/
Pros:
It's far easier on the server to serve a single large image than many small ones.
It's (slightly) faster for a web browser to load such an image.
Browsers only load images as they needs them - if you are using multiple images in a rollover, the browser would "pause" the first time you roll over the element. This can be solved using sprites, because there is only one image to load.
Cons:
It's kind of a pain to code (more so than using multiple images at least)
One often overlooked downside of using CSS sprites is memory footprint:
https://web.archive.org/web/20130605000516/http://blog.vlad1.com/2009/06/22/to-sprite-or-not-to-sprite/
Unless the sprite image is carefully constructed, you end up with
incredible amounts of wasted space. My favourite example is from WHIT
TV’s web site, where this image is used as a sprite. Note that
this is a 1299×15,000 PNG. It compresses quite well — the actual
download size is around 26K — but browsers don’t render compressed
image data. When this image is downloaded and decompressed, it will
use almost 75MB in memory (1299 * 15000 * 4).
When sprites get loaded into the browser, they are stored uncompressed. A 26 KB file can uncompress to take up a whopping 75 MB of RAM. You should be mindful of using sprites with very large dimensions.
There's also the issue of what happens in browsers with poor CSS support (legacy browsers). The sprites may end up totally broken.
Sprites
Pros:
Less HTTP connections to the server
Faster loading on broadband
Cons:
No encapsulation: If you want to change one image, you have to change the sprite
It is difficult to setup individual images in CSS without a tool
Don't degrade: If the browser don't support CSS, you are in trouble
CSS Sprites:
Pros:
Graceful degrade in unsupported browsers (text can be shown when background images for links are not allowed)
Fewer HTTP requests
Each image has a separate overhead like color table so image slicing will be having more overhead than CSS sprites
Cons:
Poses a problem if images are turned off in the browsers (rare case though)
Image slicing:
Pros:
User perceives a faster load since loaded piece by piece.
Load on demand like when the user places his mouse on the image
Cons:
The webpages might have a large size on the client side even thought it might not be the case on the server side.
The main drawback of sprites is it makes it hard to read/maintain/modify your CSS. It can be difficult to remember the exact pixel offsets within the sprite.
pros using sprites :
since it is using 1 images for all, it require less load on http server.
cons:
- hard to code. you must know the coordinate each images inside sprites so you can display it correctly. once you change the size of the image, you need to adjust all ...
- big images could creates long waited page to display. while using images, user with slow internet connection can see one by one.
best practices.
use it for example roll over images.
Look into using a CSS sprite generator (we use SmartSprites). That way you can do slices locally, and have your build process generate a spritemap. It's the best of both worlds.
Also is SmartSprites isn't for you, there's definitely others, however I like it because it reduces the amount of work up front AND during changes.
Cons
- slower on older browsers/ maybe not working on them with hover effect (opera6)
- if not used correctly can get very/too huge (group them adequately!)
- tedious work to set them up
Pros
- less bytes transfered, because one big image is smaller then all individual images combined (one header/ color table)
- less http requests
I prefer going the middle ground of grouping similar images (normal, hover, selected page, the parent page of selected page) than having all the images in one file. To make these, you image slice like normal in Photoshop or Illustrator, open the files up and combine them with a shortcut key. I wrote the Photoshop script that combines images into CSS sprites. You will have multiple HTTP connections, but won't have the load delay on hover.