简体   繁体   English

在JavaScript中以编程方式生成图像数据-uri

[英]Generate an image data-uri programmatically in javascript

I am working on a mapping project using Google Maps. 我正在使用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. 网格矩阵约为120x150,因此具有单个标量值的总共约18000个像元。 This is too many polygons to render using native Google Maps drawing. 无法使用本机Google Maps绘图渲染的多边形太多。 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. 由于无法将数据发送到服务器进行处理,因此我试图尝试一种完全使用javascript做到这一点的方法。 I know that data-uri's can be used in css, and I believe in javascript too, to store small images as strings. 我知道data-uri可以在CSS中使用,我也相信javascript,可以将小图像存储为字符串。 I am not sure if google maps will accept this natively, but that will be a separate issue. 我不确定Google Maps是否会本机接受,但这将是一个单独的问题。 For now I am just curious whether or not anyone has implemented a javascript image-generator using the data-uri model. 现在,我只是好奇是否有人使用data-uri模型实现了javascript图像生成器。 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. 我知道我可以使用canvas元素以某种方式实现此目的,这种方式在代码可读性方面更有意义,但是似乎直接生成一个字符串似乎是一个不错的解决方案。

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: 多亏了我的stackexchange问​​题上出现的侧边栏中的一些动词,我再次尝试使用一些不同的术语进行谷歌搜索,结果发现:

http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/ 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). 在循环中,我将数据调整为以平均值为中心,并标准化为跨越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);

And here is the lttleEndianHex helper function, as taken from the link above: 这是lttleEndianHex帮助器函数,如上面的链接所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM