将ajax数组缓冲区响应绘制到画布中

Draw ajax arraybuffer response into canvas

本文关键字:布中 绘制 响应 ajax 数组 缓冲区      更新时间:2023-09-26

你好,我从服务器(binay,arraybuffer)请求一个Image,然后我想将该arraybuffer转换为可以在任何画布元素上绘制的有效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,然后从中创建一个图像,然后将图像绘制到画布元素上,但我对这样的解决方案不感兴趣,因为:

  1. 使用回调

更新

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

下面是与jQuery一起使用的ajaxTransport,用于对来自服务器的图像进行二进制数组缓冲区请求:

$.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();
            }
        };
    }
});

您可以使用Blob和Blob-url设置为图像源。这比使用Base-64和DataURI稍微好一点,因为您不需要将二进制数据转换为字符串,然后再转换回来(内部)。

当数据存在于文件容器中时,不能将其直接设置为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;

Demo

// 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玩具解码为原始位图)

您也可以使用此库(PNG.js)解码PNG,而无需依赖<img>

希望画布API将来将使用类似于WebAudio API中的decodeAudioData的原生decodeImageData方法进行更新。如果没有计划,也许可以在WHATWG跟踪器上请求它?