Antialiasing text on canvas - javascript

I have to create .pngs for a lot of clients that are printed by an industrial inkjet (ads on back of a children's magazines).
Unfortunately, all browsers seem to switch on antialiasing - no matter what I try. Neither CSS nor ctx.mozImageSmoothingEnabled=false; seem to work.
Does anyone have any idea to get text displayed on canvas WITHOUT any grey-scaled pixels trying to make the font sharper?

The canvas will anti-alias everything drawn to it, with the exception of images when imageSmoothingEnabled is set to false (and then only for resampling purposes).
There are various options though -
SVG
Using SVG would be ideal as it is vectors and can be easily converted to postscript. If the printer supports postscript it will rasterize the vectors into the optimal raster-mask and make sharp edges.
Large bitmap
You can reduce the effect of anti-aliasing by using a very large bitmap, but from my own experience, and probably yours as well, it won't eliminate the gray points.
There is also the risk of meeting the limitation of canvas element itself which in some browsers is limited to 6k. Depending on the printer's DPI this may or may not be enough.
A combination of a large bitmap and threshold (see below) can perhaps get you around this though.
The Deep Dive implementation
Another way, but more advanced, to get around this is to load the font manually and draw the paths of it using Bresenham or similar algorithm. An additional aspect is that you would need to use polygon fill-algorithms as well (ie. even-odd or non-zero winding).
All this is doable without too much effort:
To load fonts and get the path data you can use f.ex. opentype.js
Use Bresenham or EFLA for rendering vectors to lines (if needed)
Use a polygon fill algorithm even-odd or non-zero winding to fill the polygons (you may get away with normal canvas fill if you can cover the edges with the Bresenham/EFLA lines).
As you are in print industry Open-Type may not be sufficient as Adobe fonts are more common from the typical repository. You can probably get the path data via other means or find the equivalent in an Open Type version or even a SVG font type.
Threshold
Another approach is to quantize the gray-levels. You can iterate over the bitmap and use a threshold value to set the pixel either transparent or solid color.
The result may not be so good as you will end up with some sharp transitions around some edges. You may however be able to reduce these artifacts depending on the print-resolution as well as the chosen threshold value.

Related

Canvas HIT testing: dealing with element boundaries and anti-aliasing

The setup
As part of a web vector editing tool written in Javascript, I'm implementing hit testing using a hit canvas strategy similar to that of Concrete.js.
For most of it, it works pretty well: I'm drawing my shapes twice (once on the display canvas, and once on a hit canvas).
When querying the canvas, I check the hovered pixel of the hit canvas and extract interaction information (i.e. which object id is stored there).
The problem
This works well inside shapes, but is painfully flawed at the boundaries where anti-aliasing makes the stored data invalid (it gets mixed with whatever background data was there before).
Are there good strategies for dealing with this data boundary problem?
Without disabling anti-aliasing for canvas methods, then we're bound to have some boundary regions across overlapping regions that will store merged data from multiple regions.
The simple scenario
In a binary scenario (some foreground vs the background), then this can be mitigated as we can assume the background to have no value, and any value becomes some foreground.
The real scenario
However, in a general scenario with multiple shapes overlapping each other on top of the background, is there any reasonable strategy for error detection? (or error correction, but I assume that's harder)
If I can tell that the data is invalid (i.e. it consists of perturbed data due to anti-aliasing), then I can use a different strategy for those few pixels at the boundaries. But I feel that it's impossible to tell whether the data I'm extracting is valid in the general scenario where we can have many overlapping shapes.
Of course, one solution is to NOT use a hit canvas. But I was wondering whether people had found a solution using hit canvases since they seem great for dealing with complex geometries.
Anti-aliasing
The ideal solution would be to disable anti-aliasing, which I don't think is possible for canvas methods [*].
[*] I know we can disable filtering when rendering images (e.g. that question) such as with imageSmoothingEnabled=false or rescaling with image-rendering: pixelated, but those don't solve the problem of anti-aliasing when drawing shapes / paths.

Change DPI of canvas element in HTML5

I'm looking to create a chrome application that allows the user to design a few different things using the canvas element. After they're done, I'd like to use a mask to crop out everything outside a specified area and then send the image to a printer. However, I need to be able to control the printed size precisely.
When I was making a similar app in python, it was a simple matter of setting the DPI to a ratio of the resolution to the dimensions I needed. I'm trying to find if there's a solution as simple as this one for HTML5.
I've found a couple posts asking for similar things, but they're unanswered and don't have a lot of activity.
Any help would be appreciated!
Canvas is a bitmap (raster) format. You can not just increase the DPI without some horrible artifacts appearing.
You can however record all the drawing, strokes/fills etc, and then at print time create a larger canvas for print and scale up all the drawing commands to fit the higher resolution canvas. As long as you don't use bitmapped images or direct pixel manipulation the results will be good. Though large canvas formats can be problematic on some devices and browsers. A better way is to convert it all to a vector format like SVG and print that. Or skip the canvas altogether and draw to SVG.

Infinite Zoom with Javascript, Jquery or HTML5 Canvas

I've seen this "The Scale of the Universe 2" and I just want to know if this can be done with javascript or jQuery or with HTML5 Canvas.
If you click an item (example the "Human") , an info will pop out beside it.
I searched for 3 days here if someone has a similar question. But I only saw Google Map like behavior where you can zoom in on the map cursor position.
Actually I want to make a "Timeline" like effect or, like the "Time Machine" Recovery on Mac OS X.
Fixed position of zoom. Not like a google map zoom, that you can pan and zoom anywhere.
Can I put (example "The human") images and text on a div?
Are there available articles/tutorials about this?
Options:
Javascript
jQuery
HTML5 Canvas and CSS3 Transform and scrolling it to Z-axis so you can zoom in/out.
Flash/Flex (Well I don't want to use lots of resources on CPU because I need it in a large resolution or in full screen.
It is possible to implement an infinite zoom in HTML canvas, this is the source code of a proof of concept that I implemented and here you can test it live.
It is actually quite tricky to implement, and most probably you'll need to use big decimals.
The approach I followed uses the same coordinate space as d3-zoom. Basically, you have three coordinates, x, y and k. K is the zoom. If k is 2 it means that you have doubled everything.
Now, if you want to do infinite zoom, it is very easy to reach k = 64, but that is already outside of float64 precision and you'll have a lot of artifacts, where translating in the image is not smooth, or you don't zoom in where you want.
One way to avoid those artifacts is to use coordinates that have infinite length, for example BigIntegers. To make my implementation easy and compatible with d3-zoom, I used big decimals instead, but I had to implement my own library of BigDecimals, basically infinite precission on the integer part and 32bits of precision on the decimal part. Of course, you also need to adapt the zooming library to support BigDecimals. Moreover, in the case of d3-zoom, a lot of calculations where done in the initial coordinate space (k=1) but division of floats will always have an error and it is also perceivable once you are deep enough. To avoid that you need to do all computations locally.
It might sound like a lot of hassle to insist on using the d3-zoom library, but zooming UX is actually tricky, specially if you combine that at different k, you'll need to consider scrolling, zooming on the phone, double tapping...
In case you want to use SVG transformations, then you'll need to fake it. You'll introduce nodes when they are barely visible, allow to scale them. However, most probably you'll also need to fake it when they are too big to avoid artifacts there.
There is no infinite zoom. However you can zoom in/out of an SVG image in HTML5 canvas.
SVG supports affine tranformation. You can set the required zoom/pan in the affine transform and show the relavant areas. The behavior/listener can be implemented in Javascript and the SVG can be rendered on HTML5 canvas.
As a starting point you can look at this example: http://www.html5canvastutorials.com/labs/html5-canvas-scaling-a-drawing-with-plus-and-minus-buttons/
This is totally doable in HTML5. Actually, any system able to display and zoom images should be able to. It's not one big image being zoomed, it's a big amount of images being zoomed (for instance the initial human is an image, which is scaled and moved out when you zoom in or out). The idea is splendid, but I don't really see any technical performance in it. As long as you correctly limit the number of images being resized and bitmapped, it should keep a decent FPS rate.

Javascript library for resampling an array?

I'm trying to visualize some data on an HTML canvas and I'm facing an issue similar to this one. That is, the size of my data doesn't exactly match the size of my canvas.
In one instance I'd like to plot a 1024 point signal on a canvas that's 100px wide. (E.g., an audio waveform.)
In another instance I'd like to show a 1024 by 5000 point matrix on a canvas that's 100 px high by by 500 px wide. (E.g., an audio spectrogram.)
In both cases, I'll need to resample my data so that it fits on the canvas. Does anyone know of a library/toolkit/function in Javascript that can do this?
** EDIT **
I'm aware that there are many techniques I could use here. One possibility is to simply discard or duplicate data points. This would do in a pinch, but discarding/duplication is known to produce results that tend to look "jagged" or "blocky" (see here and here). I'd prefer to use a slightly more sophisticated algorithm that outputs smoother images such as Lanczos, bilinear or bicubic resampling. Any of these would meet my needs.
My question isn't about which algorithm to use, though, it's about whether any of them have been implemented in open-source javascript libraries. Surprisingly, I haven't been able to find much in JS. Coding my own resampling function is obviously an option, but I wanted to check with the SO community first to make sure I wasn't re-inventing the wheel.
(This answer gives a code listing that's very close to what I want, except that it operates directly on the canvas objects rather than the data arrays, and it forces the aspect ratios of the input and output to be the same. If nothing else is available, I can definitely work with this, but I was hoping for a solution that's a bit more general and flexible, along the lines of Matlab's resample.)
use canvas scale
ctx.scale(xscale,yscale);
you can determine the scaling by calculating the rate between your canvas and the data
ctx.scale(canvas_x/data_x,canvas_y/data_y)

Modulate colors with drawImage on HTML5 canvas

I'm playing around with the idea of modifying my game development IDE to produce HTML5 versions of the games created with it. One of the features of the IDE is the ability to define frames, which not only define how a graphics cell is transformed (rotated, stretched, etc), but also how it is colored when it is drawn. So if I wanted green hills and brown hills and uphills and downhills, I would only need 1 graphic defined for all of those, simply transformed and colored differently.
I can see how an HTML5 canvas context will allow me to transform drawImage results, but I don't see a practical way to modulate the colors. I want to be able to say, for example, R=255, G=255, B=0, A=127 and have none of the blue channel come through (a yellow-tinted version of the graphic) drawn at 50% translucency (keeping in mind that portions of the graphic cell may already be translucent or transparent).
Is this possible? Or will I need to getImageData and manipulate the pixels and cache manipulated copies? If I need to cache manipulated copies, what's the best JavaScript data structure to accomplish this? I think I'd want some kind of dictionary where the key is an image index and an RGBA composed as a single value somehow. Look-ups would have to be very fast because it would potentially be done for a majority of the tiles being drawn.
Sadly I don't think you can do it without the help of getImageData.
Here's an example of tinting an image using getImageData:
http://jsfiddle.net/3eUBk/2/
It was something I made to answer this question, which has an explanation of everything thats going on: How can I use a gradient map to tone a HTML5 canvas with an image in the canvas.
Let me know if you need more information.

Categories