9

首先,我知道有实现这一点的标准方法(readAsDataURL 和 drawImage),但不幸的是,它们不适用于这个特定的用例。

我正在使用 filereader API 作为数组缓冲区读取图像,如下所示:

    var reader = new fileReader();
    reader.onload = function(e){

          var byteArray = new Uint8ClampedArray(e.target.result);
          //do stuff to this array
    }
    reader.readAsArrayBuffer(file);

然后我用这个返回的数据创建一个clampedarray。

我现在想要做的就是将这个像素数组直接绘制到画布上putImageData

目前我正在做以下事情:

var byteArray = new Uint8ClampedArray(e.target.result);
var imgdata = ctx.createImageData(img.width, img.height);
var canvdata = imgdata.data;

for (var i = 0; i < canvdata.length; i += 4) {
    canvdata[i] = byteArray[i];
    canvdata[i + 1] = byteArray[i + 1];
    canvdata[i + 2] = byteArray[i + 2];
    canvdata[i + 3] = byteArray[i + 3];
}
ctx.putImageData(imgdata, 0, 0);

使用这种方法,虽然数据被绘制到画布上,但它看起来像乱码的雪花或噪点,并不是图像的正确表示。

这使我相信我在循环中错误地构造了 imagedata 数据,或者我获取像素数组的初始方法可能不正确。

总而言之,我希望能够获取通过 html5 fileReader API 检索到的数组缓冲区(jpeg),然后创建一个与画布兼容的 imageData 数组,以便以后可以使用putImageData

提前致谢。

4

1 回答 1

8

编辑

JPEG文件不是颜色数据的简单字节数组,因此您不能像这样简单地加载它。如果您想在不直接导入画布的情况下解决此问题,则必须使用JPEG解码库,例如我通过快速谷歌搜索找到的 notmasteryet 的这个项目。

原来的

不幸的是,它们不适用于这个特定的用例

为什么它们不可用?

// example array
u = new Uint8ClampedArray(4);
u[0] = 255, u[1] = 56, u[2] = 201, u[3] = 8; // [255, 56, 201, 8]
// to String
str = String.fromCharCode.apply(null, u); // "ÿ8É"
// to Base64
b64 = btoa(str); // "/zjJCA=="
// to DataURI
uri = 'data:image/jpeg;base64,' + b64; // "data:image/jpeg;base64,/zjJCA=="

而反过来

// uri to Base64
b64 = uri.slice(uri.indexOf(',')+1);
// to String
str = atob(b64);
// to Array
arr = str.split('').map(function (e) {return e.charCodeAt(0);});
// to Uint8ClampedArray
u = new Uint8ClampedArray(arr); // [255, 56, 201, 8]
于 2013-04-24T15:11:30.540 回答