将ajax arraybuffer响应绘制到画布中

时间:2015-04-01 07:31:40

标签: javascript ajax html5 canvas

您好我从我的服务器请求一个图像(binay,arraybuffer),然后我想将该arraybuffer转换为可以在任何canvas元素上绘制的有效imageData。

除了由ajax请求生成的imageData之外,我还有其他的imageData对象,我将它们组合在画布上(为了展平图像)并生成我的最终图像。但是,如上所述,来自服务器请求的imageData会产生纯粹的噪音,我不确定我在创建有效的imageData时做错了什么。

这是我的方法,尝试将arraybuffer转换为imageData但没有成功。

ImageProcessor.prototype.imageData = function(data, width, height) {

    width = width || this.settings.width;
    height = height || this.settings.width;

    var newData = (data instanceof Uint8ClampedArray) ? data : new Uint8ClampedArray(data);
    var imageData = this.ctx.createImageData(width, height);

    imageData.data.set(newData);

    return imageData;

};

PS :我设法将arrayBuffer转换为b64图像资源-URL,然后从中创建一个图像然后将图像绘制到canvas元素上,但我和#39;我对这样的解决方案不感兴趣,因为:

  1. 在我看来有点过分

  2. 使用回调

  3. 更新

    服务器上的图像是.png文件(RGBA)。

    而bellow是与jQuery一起使用的ajaxTransport,用于从服务器执行二进制 - arraybuffer对图像的请求:

    $.ajaxTransport("+binary", function(options, originalOptions, jqXHR){
        // check for conditions and support for blob / arraybuffer response type
        if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob)))))
        {
            return {
                // create new XMLHttpRequest
                send: function(_, callback){
                    // setup all variables
                    var xhr = new XMLHttpRequest(),
                        url = options.url,
                        type = options.type,
                        // blob or arraybuffer. Default is blob
                        dataType = options.responseType || "blob",
                        data = options.data || null;
    
                    xhr.addEventListener('load', function(){
                        var data = {};
                        data[options.dataType] = xhr.response;
                        // make callback and send data
                        callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
                    });
    
                    xhr.open(type, url, true);
                    xhr.responseType = dataType;
                    xhr.send(data);
                },
                abort: function(){
                    jqXHR.abort();
                }
            };
        }
    });
    

2 个答案:

答案 0 :(得分:2)

您可以使用Blob和blob-url设置为图像源。这比使用Base-64和Data-URI略好,因为您不需要将二进制数据转换为字符串,然后返回(内部)。

当数据存在于文件容器中时,不能直接将数据设置为ImageData对象,因为必须首先解析,解压缩,解码和转换“文件”(字节数组)。

示例

var blob = new Blob([arrayBufferHere], {type: "image/png"}); // set proper mime-type

var domURL = self.URL || self.webkitURL || self,
    url = domURL.createObjectURL(blob),
    img = new Image;

img.onload = function () {
    domURL.revokeObjectURL(url);  // clean up
    // this = image
};
img.src = url;

演示

// load file:
fetch("http://i.imgur.com/rUeQDjE.png", convert, alert);

function convert(buffer) {
  var blob = new Blob([buffer], {type: "image/png"});

  var domURL = self.URL || self.webkitURL || self,
    url = domURL.createObjectURL(blob),
    img = new Image;

  img.onload = function() {
    domURL.revokeObjectURL(url); // clean up
    document.body.appendChild(this);
    // this = image
  };
  img.src = url;
}

function fetch(url, callback, error) {

  var xhr = new XMLHttpRequest();
  try {
    xhr.open("GET", url);
    xhr.responseType = "arraybuffer";
    xhr.onerror = function() {
      error("Network error")
    };
    xhr.onload = function() {
      if (xhr.status === 200) callback(xhr.response);
      else error(xhr.statusText);
    };
    xhr.send();
  } catch (err) {
    error(err.message)
  }
}

(或者,您可以使用我的 png-toy 解码到原始位图)

答案 1 :(得分:0)

您还可以使用this library (PNG.js)解码PNG,而无需依赖<img>

希望将来使用类似于Web Audio API中的decodeAudioData的本机decodeImageData方法更新canvas API。如果没有计划,可以在WHATWG跟踪器上请求它吗?