1. 程式人生 > >TypeArray、ArrayBuffer、Blob、File、DataURL、canvas的相互轉換

TypeArray、ArrayBuffer、Blob、File、DataURL、canvas的相互轉換

Blob to ArrayBuffer

var blob = new Blob([data], {type: ‘text/plain‘});
var reader = new FileReader();
reader.onload = function(e) {
    callback(e.target.result);
};
reader.readAsArrayBuffer(blob);

ArrayBuffer to Blob

var buffer = new ArrayBuffer(32);
var blob = new Blob([buffer]);       // 注意必須包裹[]

ArrayBuffer to Uint8 

Uint8陣列可以直觀的看到ArrayBuffer中每個位元組(1位元組 == 8位)的值。一般我們要將ArrayBuffer轉成Uint型別陣列後才能對其中的位元組進行存取操作。

var buffer = new ArrayBuffer(32);
var u8 = new Uint8Array(buffer);

Uint8 to ArrayBuffer

我們Uint8陣列可以直觀的看到ArrayBuffer中每個位元組(1位元組 == 8位)的值。一般我們要將ArrayBuffer轉成Uint型別陣列後才能對其中的位元組進行存取操作。

var uint8 = new Uint8Array();
var buffer = uint8.buffer; 

Array to ArrayBuffer

var arr = [0x15,0xFF,0x01,0x00,0x34,0xAB,0x11];
var uint8 = new Uint8Array(arr);
var buffer = uint8.buffer;


獲取/設定ArrayBuffer對應的數值

一串ArrayBuffer是可以被“理解”為很多個值的,以下面這個值為例,

按照服務端的協議,這串資料流的格式如下:
1 unsign byte (1位元組) + 1 unsign int (4位元組) + 1 unsign short (2位元組)

var arr = [0x01,0x02,0x00,0x00,0x00,0x00,0x03];
var u8 = new Uint8Array(arr);
var ab = u8.buffer;
console.log(ab); // ab為要解析的ArrayBuffer

var u8 = new Uint8Array(ab, 0, 1); // (arraybuffer, 位元組解析的起點, 解析的長度)
var val_byte = u8[0];
console.log(val_byte);

// 解析unsign int
// 由於Uint32Array的解析起點必須是4的整數倍,而在流中該資料的起點是1,所以選擇先“裁剪”(slice)出要解析的流片段,再用Uint32去解析該片段
var u32buff = ab.slice(1, 5);
var u32 = new Uint32Array(u32buff);
var val_uint = u32[0];
console.log(val_uint);

// 解析unsign short
var u16buff = ab.slice(5, 7);
var u16 = new Uint16Array(u16buff);
var val_short = u16[0];
console.log(val_short);

TypeArray to Array

function Uint8Array2Array(u8a) {
    var arr = [];
    for (var i = 0; i < u8a.length; i++) {
        arr.push(u8a[i]);
    }
    return arr;
}

canvas轉換為dataURL 

var png = canvas.toDataURL(‘image/png‘);
var jpg = canvas.toDataURL(‘image/jpeg‘, 0.8);


File、Blob物件轉換為dataURL

File物件也是一個Blob物件,二者的處理相同。

function readBlobAsDataURL(blob, callback) {
    var a = new FileReader();
    a.onload = function(e) {callback(e.target.result);};
    a.readAsDataURL(blob);
}
//example:
readBlobAsDataURL(blob, function (dataurl){
    console.log(dataurl);
});
readBlobAsDataURL(file, function (dataurl){
    console.log(dataurl);
});


dataURL轉換為Blob物件

function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(‘,‘), mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], {type:mime});
}
//test:
var blob = dataURLtoBlob(‘data:text/plain;base64,YWFhYWFhYQ==‘);


dataURL圖片資料繪製到canvas

先構造Image物件,src為dataURL,圖片onload之後繪製到canvas

var img = new Image();
img.onload = function(){
    canvas.drawImage(img);
};
img.src = dataurl;

File,Blob的圖片檔案資料繪製到canvas

還是先轉換成一個url,然後構造Image物件,src為dataURL,圖片onload之後繪製到canvas

利用上面的 readBlobAsDataURL 函式,由File,Blob物件得到dataURL格式的url,再參考 dataURL圖片資料繪製到canvas

readBlobAsDataURL(file, function (dataurl){
    var img = new Image();
    img.onload = function(){
        canvas.drawImage(img);
    };
    img.src = dataurl;
});


不同的方法用於構造不同型別的url (分別是 dataURL, objectURL(blobURL), filesystemURL)。這裡不一一介紹,僅以dataURL為例。

filesystemURL不是指本地檔案URL的形式(file:///….), 而是格式類似於 filesystem:http://... 的一種URL,支援沙盒檔案系統的瀏覽器支援(目前僅Chrome)支援。

Canvas轉換為Blob物件並使用Ajax傳送

轉換為Blob物件後,可以使用Ajax上傳影象檔案。

先從canvas獲取dataurl, 再將dataurl轉換為Blob物件

var dataurl = canvas.toDataURL(‘image/png‘);
var blob = dataURLtoBlob(dataurl);
//使用ajax傳送
var fd = new FormData();
fd.append("image", blob, "image.png");
var xhr = new XMLHttpRequest();
xhr.open(‘POST‘, ‘/server‘, true);
xhr.send(fd);