I am working on a mapping project using Google Maps. We have a variety of different types of data that we are displaying with different geographical boundaries. Some of the data comes from the client and is very restricted in terms of privacy and cannot be sent to the server side for processing. One of the goals of our project is to interpolate the different data sets to a common regularly-sized grid for comparison and analysis. I would like to be able to visualize the grid on the map. The grid matrix is about 120x150, so about 18000 total cells with a single scalar value. This is too many polygons to render using native Google Maps drawing. Since it is a regularly sized grid, it seems like a good solution would be to render the grid as an image and overlay that on the map as a single entity. Since I cannot send the data to the server for processing, I was trying to think of a way to do this completely in javascript. I know that data-uri's can be used in css, and I believe in javascript too, to store small images as strings. I am not sure if google maps will accept this natively, but that will be a separate issue. For now I am just curious whether or not anyone has implemented a javascript image-generator using the data-uri model. And if so, how. I have searched but not found any attempts. I have looked at file specifications, but thought I'd ask here before delving too deep into a wild goose chase / reinventing the wheel. I know that I could use a canvas element to do this in a way that is makes more sense in terms of code readability, but it seems like generating a string directly, would be an elegant solution.
-
Images as data-uris are large, canvasing is the way to go. – Etheryte Mar 03 '14 at 21:21
-
What do you mean by large? Is that just a matter of compression? Or does it have to do with the base64 encoding? I have implemented a quick test based on code from the link I found and the image it creates is about 70kb, which surely could be improved but is by no means a big deal. Creating and destroying a canvas element, writing to it, and then sending it as an overlay to google maps, seems like a lot of overhead that can be cut out by just sending a (somewhat long) string. – cheepychappy Mar 03 '14 at 22:07
1 Answers
Thanks to some of the verbiage in the sidebar that showed up on my stackexchange question, I tried googling again with some different terms and found this:
http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/
Which more or less answers my question. Still interested of others have suggestions or answers, though!
Update:
Here is the code that I ended up using. It is modified from the link above so that the loops over the grid are done bottom-top left-right so that no flipping is necessary, and I have cut out some of the ancillary functions. In my loop, I am adjusting my data to be centered around the mean and normalized to span 4 standard deviations (two positive, two negative).
var interpolation = this.interpolateGeoDataLayerToGrid();
var numFileBytes = this.getLittleEndianHex(interpolation.grid[0].length * interpolation.grid.length);
var w = this.getLittleEndianHex(interpolation.grid[0].length);
var h = this.getLittleEndianHex(interpolation.grid.length);
var header =
'BM' + // Signature
numFileBytes + // size of the file (bytes)*
'\x00\x00' + // reserved
'\x00\x00' + // reserved
'\x36\x00\x00\x00' + // offset of where BMP data lives (54 bytes)
'\x28\x00\x00\x00' + // number of remaining bytes in header from here (40 bytes)
w + // the width of the bitmap in pixels*
h + // the height of the bitmap in pixels*
'\x01\x00' + // the number of color planes (1)
'\x20\x00' + // 32 bits / pixel
'\x00\x00\x00\x00' + // No compression (0)
'\x00\x00\x00\x00' + // size of the BMP data (bytes)*
'\x13\x0B\x00\x00' + // 2835 pixels/meter - horizontal resolution
'\x13\x0B\x00\x00' + // 2835 pixels/meter - the vertical resolution
'\x00\x00\x00\x00' + // Number of colors in the palette (keep 0 for 32-bit)
'\x00\x00\x00\x00'; // 0 important colors (means all colors are important)
var imgdata = "";
for (var row=interpolation.grid.length-1; row >= 0; row--) {
for (var col=0; col<interpolation.grid[row].length; col++) {
var value = Math.min(255,Math.max(0,Math.floor(128 + 64*(interpolation.grid[row][col]-interpolation.mean)/interpolation.stdev)));
imgdata += String.fromCharCode(255-value, 0, value, 128);
}
}
var datauri = 'data:image/bmp;base64,';
if(window.btoa != undefined) {
datauri += btoa(header + imgdata);
}
else {
datauri += $.base64.encode(header + imgdata);
}
newOverlay = new google.maps.GroundOverlay(datauri,
new google.maps.LatLngBounds(
new google.maps.LatLng(this.GridDataSettings.latmin, this.GridDataSettings.longmin),
new google.maps.LatLng(this.GridDataSettings.latmax, this.GridDataSettings.longmax)
));
newOverlay.setMap(map);
And here is the lttleEndianHex helper function, as taken from the link above:
getLittleEndianHex: function(value) {
var result = [];
for (var bytes = 4; bytes > 0; bytes--) {
result.push(String.fromCharCode(value & 255));
value >>= 8;
}
return result.join('');
}

- 468
- 3
- 12
-
How do you feed an image to this? Im looking for a way to get dataURI without needing canvas. – Noitidart Feb 05 '15 at 21:00
-
1In my case, I was generating the image dynamically based on a matrix of data points that I could feed into this function so that the data-uri string could create an image element that could then be fed to google maps as an overlay element. Maybe you could explain a little more about what you are trying to do, as it sounds like you are starting with an image and want the data it contains, whereas I was doing the opposite. – cheepychappy Feb 05 '15 at 23:21
-
Thanks man for that offer to help. Yeah I was just wondering how to take an image thats a HTML image, and put it into a javascript object, then how to write it to blob/file. I found this thing called FileReader. – Noitidart Feb 05 '15 at 23:36
-
Still confused on your inputs and outputs? What do you mean by HTML image? An
tag? And what do you mean by writing it to a file? On the server? For the visitor to download? And why does the image need to get processed in javascript for either of those cases rather than through something server-side, which would be pretty much necessary in either case. Why can't the user right-click on the image in the browser to download, etc...? And why don't you want to use canvas to get the image data. You don't need to actually have a canvas element on the visible page to use the functions. – cheepychappy Feb 06 '15 at 18:45