簡體   English   中英

Uint8Array 到 JavaScript 中的圖像

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM