|
|
2
Timmmm
5 年前
我想你可以做一个
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>
元素,仅在
<canvas>
.
<img>
需要实际的图像文件。
幸运的是,BMP格式得到了广泛支持,并支持原始RGBA数据。你只需要预先准备一个合适的BMP头。完成后,您可以将数据传递给
<img>
使用Ben Fortune概述的技术。我会的
不
使用
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没有,苹果的finder也没有。如果你在写一个电子应用程序,应该没问题,但我不会在网上使用它。
然而,既然你已经将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,但因为我将压缩设置为
比奥RGB
alpha通道被忽略。这有点浪费内存。你可以设置为
24 BPP
取而代之,然后每像素只使用3个字节,但需要注意的是,每一行必须填充到4个字节的倍数,我不想在这里这么做。
|