I am using Mapbox GL JS to overlay an image of satellite data over Texas. The image is big enough to cover Texas, but even when using 100% correct geo-coords, the image is not in the correct place. I have to split the image into 6 long (west-east) images like such, and stack them vertically in separate image overlays :
This produces the desired result :
When using the 6 stacked image overlays (each 2 degrees tall and very wide to cover the state's width, by the way), the placement of the clouds is exactly perfect with zero issues. It's perfect except that having to make 6 image overlays to build this is not at all ideal and it adding processing constraints.
If I merge all the images into one big picture and overlay it using the same coords - the effect is wrong. Even though the image is exactly the same. I have highlighted the coastline so you can see that when using one large image overlay for the whole state, it becomes inaccurate. For a storm chaser (my target audience) this would not be unacceptable. I have tried manually adjusting the images but it is no good and I have wasted days of my life tracking this issue down, and it is absolutely Mapbox. I have ruled out the other possibilities like bugs in the software I use to get the data.
Here is the bad result with one overlay as opposed to splitting it vertically :
Are there any ideas to what may be causing this, and a solution? I am completely lost.
I had solved this long ago but since others have the same problem, it deserves an answer here. The problem has to do with projection. Images can be sliced and diced exactly by coordinates but they must match the projection of the map they are being overlaid on. In the case of Mapbox, it uses web mercator and images must be reprojected to EPSG:3857.
A utility to convert images (such as geoTIF) to this projection is GDAL (https://gdal.org/). A command using GDAL tools to convert an image would be something like :
gdalwarp -t_srs EPSG:3857 input.tif input-projected.tif
Hopefully this clears things up. These issues are basic knowledge in the GIS community. If you want to work with data like this, I can say that I recommend doing what I did : learn basic GIS tools and how they work. It will save you.
I'm trying to create a polygon that has un-antialiased, unfeathered, unsoftened, etc. edges/sides. My goal is to have a polygon that has visible pixelated edges like an old-school game would. I found that images do not use antialiasing with proper settings, but I'd like to use lineTo and paths to create the polygon (because I need to be able to change the colors etc).
Using scaling (setting the canvas size one fourth of the actual size and scaling the canvas up with CSS styling), translating the shape by 0.5 pixels and setting the image-rendering property to pixelated results in this:
https://jsfiddle.net/6gbo7x3g/4/
Even though the result is better than without the tricks, you can still see antialiasing. The browser support isn't great either, as pixelated image rendering isn't supported in Safari. Here is a screenshot from Chrome of the canvas above:
image of antialiased polygon
How can I create a polygon (that has diagonal edges) un-antialiased? There will be multiple similar polygons, so drawing every pixel by hand would be too resource-intensive.
Questions like How can I keep the edge pixels of lines from being semi-transparent?, stackoverflow.com/a/45749684/1693593 and stackoverflow.com/a/18551803/1693593 aren't duplicates, because they only apply to scenarios where pixel-by-pixel rendering is applicable (in this scenario it is too resource-intensive). I asked this question, because other questions date almost four years back, and surely the web standards have changed since then.
I'm trying to display a large number of images on a d3 display using T-SNE. The x and y coordinates are pre-calculated, the location on the svg area is adjusted using using translate/zoom.
At the moment they all display using the precalculated coordinates.
and they remain in place as zooming/panning.
I'm looking to use collision detection (like this example) to adjust the images locations slightly so that they don't overlap, but as much as possible maintain the rough global structure.
Here's my attempt so far
https://gist.github.com/GerHarte/329af8ee5ffd8a1f87c5
With this it loads as in the image above, but as soon as I pan or zoom, all the points expand out hugely to a completely different location on the canvas and look like this, they don't seem to overlap, but they're extremely far apart.
Is there something wrong in my code or is there a better way to approach this?
Update:
I followed Lar's answer here, with the slight addition of setting the raw data points to where Lar's code settles since the points are translated when zooming or panning. The results look great (see below), but for a larger number of points (5000+) it seems to crash before converging on a final result.
Are there any suggestions to improve the efficiency with this approach? Going to try the Multi-Foci Forced Directed approach.
After setting a certain colour as the fillStyle of the canvas and drawing a rectangle with fillRect, the colour of the rectangle sometimes differs a bit from the one provided (the getImageData returns different values - usually one of them is lower by 1). It seems to happen only when using rgba colours (and not with rgb) but I actually do need to use the alpha channel.
I've made a simple test suite on js fiddle for anyone who would like to look into this issue:
http://jsfiddle.net/LaPdP/1/
Any ideas on why is this happening and if there is any way to fix that? If it at least happened always on the same value then I'd just bypass it by increasing it by 1, but it seems quite random to me.
Update from 2017: I forgot completely about this answer, but the cause is related to pre-multiplying the data, when getting/setting. As the numbers in a bitmap is always integer there will be rounding errors as the natural result of pre-multiplying often result in non-integer numbers.
There is unfortunately no convenient way to fix this.
Just to clarify about gamma below: Gamma (via a gamma setting or an ICC profile) will affect images directly, but for shapes drawn directly to the canvas this should not be a problem per-se as only the display gamma is adjusted on top, not the data itself.
Old answer:
What you are experiencing is probably a result of only a partial implementation of the color and gamma correction section in the canvas standard.
The reason for various color values, at least when it comes to images containing ICC profiles, is due to the built-in color and gamma correction in the browsers:
4.8.11.1 Color spaces and color correction
The canvas APIs must perform color correction at only two points: when
rendering images with their own gamma correction and color space
information onto the canvas, to convert the image to the color space
used by the canvas (e.g. using the 2D Context's drawImage() method
with an HTMLImageElement object), and when rendering the actual canvas
bitmap to the output device.
Source: w3.org
However, it also states in section 4.8.11.1:
Note: Thus, in the 2D context, colors used to draw shapes onto the
canvas will exactly match colors obtained through the getImageData()
method.
As the status as this is written is a work in progress my guess is that the browsers has a "lazy" implementation of color and gamma correction which currently also affects shapes - or - all color information from the canvas is corrected to display profile as the latter point in first quote. This will perhaps not change until the standard becomes final.
So I have an animation that I'm coding in javascript and HTML5 (no libraries, no plugins, no nothing and I'd like it to stay that way). The animation uses physics (basically a bunch of unusual springs attached to masses) to simulate a simple liquid. The output from this part of the program is a grid (2d-array) of objects, each with a z value. This works quite nicely. My problem arises when drawing the data to an HTML5 Canvas.
That's what it looks like. Trust me, it's better when animated.
For each data point, the program draws one circle with a color determined by the z value. Just drawing these points, however, the grid pattern is painfully obvious and it is difficult to see the fluid that it represents. To solve this, I made the circles larger and more transparent so that they overlapped each other and the colors blended, creating a simple convolution blur. The result was both fast and beautiful, but for one small flaw:
As the circles are drawn in order, their color values don't stack equally, and so later-drawn circles obscure the earlier-drawn ones. Mathematically, the renderer is taking repeated weighted averages of the color-values of the circles. This works fine for two circles, giving each a value of 0.5*alpha_n, but for three circles, the renderer takes the average of the newest circle with the average of the other two, giving the newest circle a value of 0.5*alpha_n, but the earlier circles each a value of 0.25*alpha_n. As more circles overlap, the process continues, creating a bias toward newer circles and against older ones. What I want, instead, is for each of three or more circles to get a value of 0.33*alpha_n, so that earlier circles are not obscured.
Here's an image of alpha-blending in action. Notice that the later blue circle obscures earlier drawn red and green ones:
Here's what the problem looks like in action. Notice the different appearance of the left side of the lump.
To solve this problem, I've tried various methods:
Using different canvas "blend-modes". "Multiply" (as seen in the above image) did the trick, but created unfortunate color distortions.
Lumping together drawing calls. Instead of making each circle a separate canvas path, I tried lumping them all together into one. Unfortunately, this is incompatible with having separate fill colors and, what's more, the path did not blend with itself at all, creating a matte, monotone silhouette.
Interlacing drawing-order. Instead of drawing the circles in 0 to n order, I tried drawing first the evens and then the odds. This only partially solved the problem, and created an unsightly layering pattern in which the odds appeared to float above the evens.
Building my own blend mode using putImageData. I tried creating a manual pixel-shader to suit my needs using javascript, but, as expected, it was far too slow.
At this point, I'm a bit stuck. I'm looking for creative ways of solving or circumnavigating this problem, and I welcome your ideas. I'm not very interested in being told that it's impossible, because I can figure that out for myself. How would you elegantly draw a fluid from such data-points?
If you can decompose your circles into two groups (evens and odds), such that there is no overlap among circles within a group, the following sequence should give the desired effect:
Clear the background
Draw the evens with an alpha of 1.0 (opaque)
Draw the odds with an alpha of 1.0 (opaque)
Draw the evens with an alpha of 0.5
Places which are covered by neither evens nor odds will show the background. Those which are covered only by evens will show the evens at 100% opacity. Those covered by odds will show the odds with 100% opacity. Those covered by both will show a 50% blend.
There are other approaches one can use to try to blend three or more sets of objects, but doing it "precisely" is complicated. An alternative approach if one has three or more images that should be blended uniformly according to their alpha channel is to repeatedly draw all of the images while the global alpha decays from 1 to 0 (note that the aforementioned procedure actually does that, but it's numerically precise when there are only two images). Numerical rounding issues limit the precision of this technique, but even doing two or three passes may substantially reduce the severity of ordering-caused visual artifacts while using fewer steps than would be required for precise blending.
Incidentally, if the pattern of blending is fixed, it may be possible to speed up rendering enormously by drawing the evens and odds on separate canvases not as circles, but as opaque rectangles, and subtracting from the alpha channel of one of the canvases the contents of a a fixed "cookie-cutter" canvas or fill pattern. If one properly computes the contents of cookie-cutter canvases, this approach may be used for more than two sets of canvases. Determining the contents of the cookie-cutter canvases may be somewhat slow, but it only needs to be done once.
Well, thanks for all the help, guys. :) But, I understand, it was a weird question and hard to answer.
I'm putting this here in part so that it will provide a resource to future viewers. I'm still quite interested in other possible solutions, so I hope others will post answers if they have any ideas.
Anyway, I figured out a solution on my own: Before drawing the circles, I did a comb sort on them to put them in order by z-value, then drew them in reverse. The result was that the highest-valued objects (which should be closer to the viewer) were drawn last, and so were not obscured by other circles. The result is that the obscuring effect is still there, but it now happens in a way that makes sense with the geometry. Here is what the simulation looks like with this correction, notice that it is now symmetrical: