摘要:位無符號整數(shù),長度個字節(jié),溢出處理為最大值。所以你拿到的英文字母編碼前后一樣的,但是漢字等字符就不同了。為了直接得到漢字的碼,使用其實(shí)還可以選擇使用處理漢字,但是英文又不能正常轉(zhuǎn)換了。
原文鏈接:https://ssshooter.com/2019-04...
之前做文件上傳和 canvas 修圖時接觸到幾個格式,這里打算整理一下他們的關(guān)系
Blob使用 input 獲取文件時,你拿到的就是 file 對象,而 file 繼承于 blob,所以直接講比較陌生的 blob 吧。
BLOB (binary large object),二進(jìn)制大對象,是一個可以存儲二進(jìn)制文件的“容器”。
Blob 有什么用使用 Blob 可以讓你在瀏覽器生成一個臨時文件,使用 URL.createObjectURL() 獲取他的鏈接,你就能像服務(wù)器文件一樣使用他。
let temp = new Blob(["hello fantasy"]) URL.createObjectURL(temp) // 返回 "blob:https://ssshooter.com/1bf84bba-b53a-4155-8348-33a487e8ab7e"
返回的 url 前面是主機(jī),后面是一個唯一識別碼。
在創(chuàng)建這個臨時文件后,只要不關(guān)閉當(dāng)前頁面,這個文件就會一直存在于內(nèi)存,你需要主動運(yùn)行 URL.revokeObjectURL(url) 刪除引用。
從 Blob 中提取數(shù)據(jù)在控制臺打出 blob 你根本不知道里面是啥,那么怎么讀取 blob 呢?
借助 FileReader,你可以把 Blob 讀取為 Buffer。
FileReader 對象允許 Web 應(yīng)用程序異步讀取存儲在用戶計算機(jī)上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 File 或 Blob 對象指定要讀取的文件或數(shù)據(jù)。
var reader = new FileReader() reader.addEventListener("loadend", function() { // reader.result 包含轉(zhuǎn)化為類型數(shù)組的blob }) reader.readAsArrayBuffer(blob)ArrayBuffer
經(jīng)過 FileReader 的讀取,你能看到計算機(jī)儲存數(shù)據(jù)的本質(zhì) —— 二進(jìn)制數(shù)據(jù)。
ArrayBuffer 的編輯ArrayBuffer 類似數(shù)組,每一格放入 1Byte(8bit)數(shù)據(jù),也就是八位的 0 或 1,所以換成十進(jìn)制一格最大是 255.
例如:
ArrayBuffer 不能直接操作,而是要通過類型數(shù)組對象(下面列出來的)或 DataView 對象來操作,它們會將緩沖區(qū)中的數(shù)據(jù)表示為特定的格式,并通過這些格式來讀寫緩沖區(qū)的內(nèi)容。
Int8Array:8 位有符號整數(shù),長度 1 個字節(jié),溢出處理為 數(shù)值%(取模)255。
Uint8Array:8 位無符號整數(shù),長度 1 個字節(jié)。
Uint8ClampedArray:8 位無符號整數(shù),長度 1 個字節(jié),溢出處理為 255(最大值)。
Int16Array:16 位有符號整數(shù),長度 2 個字節(jié)。
Uint16Array:16 位無符號整數(shù),長度 2 個字節(jié)。
Int32Array:32 位有符號整數(shù),長度 4 個字節(jié)。
Uint32Array:32 位無符號整數(shù),長度 4 個字節(jié)。
Float32Array:32 位浮點(diǎn)數(shù),長度 4 個字節(jié)。
Float64Array:64 位浮點(diǎn)數(shù),長度 8 個字節(jié)。
對應(yīng)視圖的轉(zhuǎn)換還很神奇的,ArrayBuffer 是一個格子 8 位,也就是跟 xx8Array 是一樣的,自然不用轉(zhuǎn)換,而 16 之后的都是把每幾個格子合成一個。
// 創(chuàng)建 buffer ab = new ArrayBuffer(4) // 創(chuàng)建視圖 a = new Uint8Array(ab) // 通過視圖操作 buffer a[0] = 2 a[1] = 25 a[2] = 31 a[2] = 233
打印 ab 會輸出:
為了方便理解他們?nèi)绾无D(zhuǎn)換,我把他轉(zhuǎn)為 2 進(jìn)制:
// Int16Array ;["1100100000010", "11101001"] // Int32Array ;["111010010001100100000010"] // Uint8Array ;["10", "11001", "11101001", "0"]
可能還沒能看出來?那再在前面補(bǔ) 0:
// Int16Array ;["0001100100000010", "0000000011101001"] // Int32Array ;["00000000111010010001100100000010"] // Uint8Array ;["00000010", "00011001", "11101001", "00000000"]
這就很明顯能看出:要轉(zhuǎn)換就要在分組之后把同一組數(shù)據(jù)從右到左拼接。
不過我自覺一般不太會用到這么細(xì)致的 bit 操作(
canvas 與 buffer另外,canvas 可以通過 ctx.createImageData() 得到 ImageData。
ImageData.data 就是一個 Uint8ClampedArray,里面順序放著圖片每一個像素的 rgba 值。你可以對這個 Uint8ClampedArray 進(jìn)行一系列操作,再用 canvas.toBlob 這個 buffer 變回 Blob,就完成了圖片編輯的操作。
通過這個操作,再結(jié)合一些卷積核相關(guān)知識,就能完成類似這個卷積核圖片修改器的功能。
Data UrlData Url 是一個前綴為 data: 的協(xié)議,你可以借助這個協(xié)議在文檔中嵌入一些小文件(最常見就是內(nèi)聯(lián)圖片了),數(shù)據(jù)格式如下:
data:[][;base64],
mediatype 填入MIME 類型,MIME 也用于服務(wù)器返回數(shù)據(jù)時指定數(shù)據(jù)類型;base64 是一種編碼方式;后面接著就是數(shù)據(jù)本體。
幾個例子:
普通文字:data:,Hello%2C%20World!
base64 處理的文字:data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D
html 文檔:data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E
執(zhí)行 script 的 html 文檔:data:text/html,
base64上面提到的 base64 不算是一種加密算法,它只是簡單地將每 3 個 8bit 字符轉(zhuǎn)換為 4 個 6Bit 字符(base64 只有 2^6 = 64 種字符,因此得名),這樣保證了傳輸中必定使用 ASCII 中可見字符,不會出奇怪的空白字符或是功能性標(biāo)志 。
由于是 3 個字符變 4 個,那么很明顯了,base64 編碼后,編碼對象的體積會變成原來的 4/3 倍。
特別要注意的是如果 bit 數(shù)不能被 3 整除,需要在末尾添加 1 或 2 個 byte(8 或 16bit),并且末尾的 0 不使用 A 而使用 =,這就是為什么 base64 有的編碼結(jié)果后面會有一或兩個等號。
喜聞樂見的舉例時間:
前置知識點(diǎn):utf8 與 unicode 的關(guān)系
你可以使用 charCodeAt() 獲取一個字符的 unicode 編碼(0 到 65535 之間的整數(shù)),但是 unicode 只是一個碼表,并不是一個具體的編碼方式,utf8 才是。所以你拿到的英文字母編碼前后一樣的,但是漢字(等字符)就不同了。
為了直接得到漢字的 utf8 碼,使用 TextEncoder(其實(shí)還可以選擇使用 encodeURIComponent 處理漢字,但是英文又不能正常轉(zhuǎn)換了)。
下面用 JavaScript 簡單寫個 base64 轉(zhuǎn)換流程:
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" Array.from(new TextEncoder().encode("碧藍(lán)幻想")) .map(val => val.toString(2).padStart(8, 0)) // 轉(zhuǎn)二進(jìn)制,補(bǔ)充到八位 .join("") .replace(/([10]{6})/g, "$1,") // 每六位插個逗號用于拆分 .split(",") // 拆分為每 6 位一組 .map(val => parseInt(val.padEnd(6, 0), 2)) // 補(bǔ)充后面的 0(但是沒有補(bǔ)夠) .map(val => b64[val]) .join("")
結(jié)果基本是對的,但是后面的 = 還是用了普通的 A 而且位數(shù)沒有加夠,所以上面轉(zhuǎn)換出來的不是標(biāo)準(zhǔn) base64,僅供參考
base64 算法參考
blob url 與 Data Url 對比blob url
不需要做編碼,省了運(yùn)算資源
大小也不會改變
在不使用時需要手動刪除引用
關(guān)閉頁面鏈接自動廢棄
Data Url
需要編碼,且體積變大 1.3 倍
容易刪除
鏈接不變,保存了可以以后使用
參考
mdn Blob
mdn FileReader
mdn HTMLCanvasElement
阮一峰 ES6 arraybuffer
進(jìn)階 FileAPI 實(shí)現(xiàn)標(biāo)準(zhǔn)
javascript info - blob
附錄 N 進(jìn)制數(shù)的表示方法// 10 var a = 10 // 8 var b = 0o1234567 // 或直接在前面加0,如果后面數(shù)字都小于8就自動變成8進(jìn)制 var c = 01234567 // 2 var d = 0b1010101110101 // 16 var e = 0xe87a90N 進(jìn)制數(shù)轉(zhuǎn) 10 進(jìn)制
parseInt(0o1234567, 8) parseInt(0b1010101110101, 2) parseInt(0xe87a90, 16)10 進(jìn)制數(shù)轉(zhuǎn) N 進(jìn)制
;(123456).toString(2) ;(123456).toString(8) ;(123456).toString(16)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105969.html
摘要:常見的源碼轉(zhuǎn)換,主要是以下三種情況壓縮,減小體積。該項(xiàng)是一個數(shù)組,表示可能存在多個文件合并。第一層是行對應(yīng),以分號表示,每個分號對應(yīng)轉(zhuǎn)換后源碼的一行。在這個位中,左邊的第一位最高位表示是否連續(xù)。 這兩天完成了自己的個人任務(wù),準(zhǔn)備學(xué)習(xí)一下前輩們的經(jīng)驗(yàn)教訓(xùn),在項(xiàng)目組的文檔中發(fā)現(xiàn)了一個要求注意的點(diǎn),如下: Js文件的開頭可以加上類似//@ sourceURL=jquery.extends.j...
閱讀 2682·2021-09-13 10:26
閱讀 1933·2021-09-03 10:28
閱讀 2008·2019-08-30 15:44
閱讀 824·2019-08-29 14:07
閱讀 412·2019-08-29 13:12
閱讀 2170·2019-08-26 11:44
閱讀 2361·2019-08-26 11:36
閱讀 2032·2019-08-26 10:19