以编程方式在javascript中生成图像数据

时间:2014-03-03 21:12:53

标签: javascript image data-uri

我正在使用Google地图开展地图项目。我们有各种不同类型的数据,我们以不同的地理边界显示。某些数据来自客户端,在隐私方面受到很大限制,无法发送到服务器端进行处理。我们项目的目标之一是将不同的数据集插入到常见的大小网格中进行比较和分析。我希望能够在地图上可视化网格。网格矩阵大约为120x150,因此大约18000个单元格具有单个标量值。这是使用本机Google地图绘制渲染的多边形太多。由于它是一个规则大小的网格,似乎一个很好的解决方案是将网格渲染为图像并将其作为单个实体覆盖在地图上。由于我无法将数据发送到服务器进行处理,因此我试图想办法在javascript中完全执行此操作。我知道data-uri可以在css中使用,我也相信javascript,将小图像存储为字符串。我不确定谷歌地图是否会接受这种原生,但这将是一个单独的问题。现在我只是好奇是否有人使用data-uri模型实现了javascript图像生成器。如果是这样,怎么样。我搜索过但没有找到任何尝试。我已经查看了文件规格,但是我想在这里深入研究一个疯狂的鹅追逐/重新发明轮子之前我会问这里。我知道我可以使用canvas元素以一种在代码可读性方面更有意义的方式来执行此操作,但它似乎是直接生成字符串,这将是一个优雅的解决方案。

1 个答案:

答案 0 :(得分:1)

感谢侧边栏中出现的一些问题出现在我的stackexchange问​​题上,我尝试用一​​些不同的术语再次搜索谷歌并发现:

http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/

或多或少回答了我的问题。尽管如此,仍然对其他人有兴趣提出建议或答案!

更新

这是我最终使用的代码。它是从上面的链接修改的,因此网格上的循环是从左上方左上方完成的,因此不需要翻转,我已经删除了一些辅助功能。在我的循环中,我将我的数据调整为以均值为中心并标准化为跨越4个标准差(两个正,两个负)。

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);

这是lttleEndianHex辅助函数,取自上面的链接:

getLittleEndianHex: function(value) {
  var result = [];   
  for (var bytes = 4; bytes > 0; bytes--) {
    result.push(String.fromCharCode(value & 255));
    value >>= 8;
  }
  return result.join('');
}