[英]Uint8Array to image in JavaScript
我有名為 frameBytes 的 Uint8Array。 我已經用這段代碼從這個字節數組中創建了 RGBA 值。
for (var i = 0; i < frameBytes.length; i++) {
imgData.data[4 * i] = frameBytes[i];// red
imgData.data[4 * i + 1] = frameBytes[i]; // green
imgData.data[4 * i + 2] = frameBytes[i];// blue
imgData.data[4 * i + 3] = 255; // alpha
}
然后我使用以下代碼將此 GRBA 值顯示到畫布上。
var ctx = fingerFrame.getContext('2d');
var imgData = ctx.createImageData(fingerFrame.width, fingerFrame.height);
ctx.putImageData(imgData, 0, 0, 0, 0, fingerFrame.width, fingerFrame.height);
在那之后,我曾經使用以下代碼在畫布中對圖像標記進行圖像處理:
const img = document.getElementById('i');
img.src = fingerFrame.toDataURL();
但我不想使用畫布。 我想直接在 Uint8Array 的圖像標簽中顯示圖像。 我怎樣才能做到這一點? 任何幫助將不勝感激。
我想直接在 Uint8Array 的圖像標簽中顯示圖像
使用 Blob 非常簡單:
// Small red dot image const content = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 5, 0, 0, 0, 5, 8, 6, 0, 0, 0, 141, 111, 38, 229, 0, 0, 0, 28, 73, 68, 65, 84, 8, 215, 99, 248, 255, 255, 63, 195, 127, 6, 32, 5, 195, 32, 18, 132, 208, 49, 241, 130, 88, 205, 4, 0, 14, 245, 53, 203, 209, 142, 14, 31, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130]); document.getElementById('my-img').src = URL.createObjectURL( new Blob([content.buffer], { type: 'image/png' } /* (1) */) );
Should display a small red dot: <img id="my-img">
(1) 它也可以在不指定 Blob MIME 類型的情況下工作。
我認為您可以從該頁面上的示例中直接制作ImageData
:
const arr = new Uint8ClampedArray(40000);
// Iterate through every pixel
for (let i = 0; i < arr.length; i += 4) {
arr[i + 0] = 0; // R value
arr[i + 1] = 190; // G value
arr[i + 2] = 0; // B value
arr[i + 3] = 255; // A value
}
// Initialize a new ImageData object
let imageData = new ImageData(arr, 200);
不幸的是,似乎沒有任何方法可以在<img>
元素中顯示ImageData
,只能在<canvas>
。 <img>
需要一個實際的圖像文件。
幸運的是,BMP 格式得到了廣泛的支持,並且支持原始 RGBA 數據。 您只需要在前面添加一個適當的 BMP 標頭。 完成后,您可以使用 Ben Fortune 概述的技術將數據傳遞到<img>
。 我不會使用data:
URL,即使你發現網上到處都有人在使用它。 這是不必要的低效。
這是一些示例代碼。 它將像素數據附加到單個緩沖區中的位圖標頭,因為這樣會更有效率。 如果您已經擁有數據,您可以為標頭創建一個單獨的Uint8Array
並將它們連接到Blob
構造函數中,即new Blob([header, pixels])
。 我沒試過。
const header_size = 70; const width = 255; const height = 255; const image_size = width * height * 4; const arr = new Uint8Array(header_size + image_size); const view = new DataView(arr.buffer); // File Header // BM magic number. view.setUint16(0, 0x424D, false); // File size. view.setUint32(2, arr.length, true); // Offset to image data. view.setUint32(10, header_size, true); // BITMAPINFOHEADER // Size of BITMAPINFOHEADER view.setUint32(14, 40, true); // Width view.setInt32(18, width, true); // Height (signed because negative values flip // the image vertically). view.setInt32(22, height, true); // Number of colour planes (colours stored as // separate images; must be 1). view.setUint16(26, 1, true); // Bits per pixel. view.setUint16(28, 32, true); // Compression method, 6 = BI_ALPHABITFIELDS view.setUint32(30, 6, true); // Image size in bytes. view.setUint32(34, image_size, true); // Horizontal resolution, pixels per metre. // This will be unused in this situation. view.setInt32(38, 10000, true); // Vertical resolution, pixels per metre. view.setInt32(42, 10000, true); // Number of colours. 0 = all view.setUint32(46, 0, true); // Number of important colours. 0 = all view.setUint32(50, 0, true); // Colour table. Because we used BI_ALPHABITFIELDS // this specifies the R, G, B and A bitmasks. // Red view.setUint32(54, 0x000000FF, true); // Green view.setUint32(58, 0x0000FF00, true); // Blue view.setUint32(62, 0x00FF0000, true); // Alpha view.setUint32(66, 0xFF000000, true); // Pixel data. for (let w = 0; w < width; ++w) { for (let h = 0; h < height; ++h) { const offset = header_size + (h * width + w) * 4; arr[offset + 0] = w; // R value arr[offset + 1] = h; // G value arr[offset + 2] = 255-w; // B value arr[offset + 3] = 255-h; // A value } } const blob = new Blob([arr], { type: "image/bmp" }); const url = window.URL.createObjectURL(blob); const img = document.getElementById('i'); img.src = url;
<img id="i">
一個很大的警告是,這種 BMP 的 RGBA 變體根本沒有得到廣泛支持。 Chrome 似乎支持它。 Firefox 沒有,Apple 的 finder 也沒有。 如果您正在編寫 Electron 應用程序,那應該沒問題,但我不會在網絡上使用它。
但是,由於您已將 alpha 設置為 255,我猜您甚至不需要 alpha 通道。 在這種情況下,您可以改用BI_RGB
:
const header_size = 54; const width = 255; const height = 255; const image_size = width * height * 4; const arr = new Uint8Array(header_size + image_size); const view = new DataView(arr.buffer); // File Header // BM magic number. view.setUint16(0, 0x424D, false); // File size. view.setUint32(2, arr.length, true); // Offset to image data. view.setUint32(10, header_size, true); // BITMAPINFOHEADER // Size of BITMAPINFOHEADER view.setUint32(14, 40, true); // Width view.setInt32(18, width, true); // Height (signed because negative values flip // the image vertically). view.setInt32(22, height, true); // Number of colour planes (colours stored as // separate images; must be 1). view.setUint16(26, 1, true); // Bits per pixel. view.setUint16(28, 32, true); // Compression method, 0 = BI_RGB view.setUint32(30, 0, true); // Image size in bytes. view.setUint32(34, image_size, true); // Horizontal resolution, pixels per metre. // This will be unused in this situation. view.setInt32(38, 10000, true); // Vertical resolution, pixels per metre. view.setInt32(42, 10000, true); // Number of colours. 0 = all view.setUint32(46, 0, true); // Number of important colours. 0 = all view.setUint32(50, 0, true); // Pixel data. for (let w = 0; w < width; ++w) { for (let h = 0; h < height; ++h) { const offset = header_size + (h * width + w) * 4; arr[offset + 0] = w; // R value arr[offset + 1] = h; // G value arr[offset + 2] = 255-w; // B value // arr[offset + 3] is ignored but must still be present because we specified 32 BPP } } const blob = new Blob([arr], { type: "image/bmp" }); const url = window.URL.createObjectURL(blob); const img = document.getElementById('i'); img.src = url;
<img id="i">
在上面的示例中,我仍然使用 32 BPP,但是因為我將壓縮設置為BI_RGB
,所以忽略了 alpha 通道。 這有點浪費內存。 您可以將其設置為24 BPP
,然后每個像素只使用 3 個字節,但需要注意的是,每一行都必須填充到最多 4 個字節的倍數,我不能在這里費心去做。
如果您知道模仿類型,則可以創建一個Blob 。
const blob = new Blob(imgData.data, 'image/png');
const url = window.URL.createObjectURL(blob);
const img = document.getElementById('i');
img.src = url;
我相信您可以使用 btoa 函數,該函數將創建圖像數據的 base64 ASCII 表示形式。
const img = document.getElementById('i');
//ImageDataArrayBuffer is your uint8 Array Buffer
img.src = "data:image/png;base64,"+ btoa(String.fromCharCode.apply(null, ImageDataArrayBuffer));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.