在计算机图形学中,BPP(Bits Per Pixel)代表每像素的颜色深度,也就是存储一个像素所需的位数。BPP越高,图像的颜色表现力越丰富,但所需的存储空间也越大。
具体来说,BPP值与图像中每个像素可以表示的颜色数量直接相关。例如,8BPP的图像每个像素使用8位来表示颜色,可以表示256种颜色。而24BPP的图像,每个像素使用24位,其中红、绿、蓝各8位,可以表示超过1600万种颜色,通常用于高质量的真彩色图像。
使用图片数据创建PixelMap对象可使用image.createPixelMap,常用的深度BPP与图片像素的关系如下所示。
BPP | 说明 | 输出格式 |
|---|---|---|
1 | 二值图(黑白图) | 每个像素用1位表示是黑色还是白色。 |
8 | 灰度图 | 灰度图像,每个像素用8位表示,可表示256种灰度。 |
24 | RGB彩色图 | RGB 真彩色,每个像素用24位表示(8位红色+8位绿色+8位蓝色),可表示1677万种颜色,是目前最常见的图像格式之一。 |
32 | ARGB彩色图 | RGB真彩色加上Alpha通道(透明度),每个像素用32位表示,可以实现半透明效果。 |
将不同深度的图像数据转换为PixelMap,为了保证图片正常显示,需要确定图像数据宽度的准确性,将图像二进制数据ImageData保存在文件中并引用。参考如下:
import { image } from '@kit.ImageKit';
import { buffer } from '@kit.ArkTS';
import { imageData } from '../common/ImageData';
function convertBitmapArrayToPixels(readBuffer: ArrayBuffer, width: number, height: number, bpp: number) {
let byteBuffer: Uint8Array = new Uint8Array(readBuffer);
let byteBufferTemp: Uint8Array = new Uint8Array(new ArrayBuffer(readBuffer.byteLength));
// 二值化黑白图,每个比特表示像素是黑色还是白色
if (bpp == 1) {
byteBufferTemp = new Uint8Array(new ArrayBuffer(byteBuffer.byteLength * 8 * 4));
for (let index = 0; index < byteBuffer.length; index++) {
for (let i = 0; i < 8; i++) {
let value: number = (byteBuffer[index] >> (7 - i)) & 0x00000001;
if (value == 1) {
byteBufferTemp[(index * 8 + i) * 4] = 255;
byteBufferTemp[(index * 8 + i) * 4 + 1] = 255;
byteBufferTemp[(index * 8 + i) * 4 + 2] = 255;
byteBufferTemp[(index * 8 + i) * 4 + 3] = 255;
} else {
byteBufferTemp[(index * 8 + i) * 4] = 0;
byteBufferTemp[(index * 8 + i) * 4 + 1] = 0;
byteBufferTemp[(index * 8 + i) * 4 + 2] = 0;
byteBufferTemp[(index * 8 + i) * 4 + 3] = 255;
}
}
}
}
// 灰度化灰度图,每个字节表示像素的灰度值
if (bpp == 8) {
byteBufferTemp = new Uint8Array(new ArrayBuffer(readBuffer.byteLength * 4));
for (let index = 0; index < byteBuffer.length; index++) {
let value = byteBuffer[index];
byteBufferTemp[index * 4] = value;
byteBufferTemp[index * 4 + 1] = value;
byteBufferTemp[index * 4 + 2] = value;
byteBufferTemp[index * 4 + 3] = 255;
}
}
// RGB彩色图,每三个字节表示像素的rgb颜色
if (bpp == 24) {
byteBufferTemp = new Uint8Array(new ArrayBuffer(4 * byteBuffer.byteLength / 3));
for (let i = 0; i < byteBuffer.length / 3; i++) {
byteBufferTemp[i * 4] = byteBuffer[i * 3];
byteBufferTemp[i * 4 + 1] = byteBuffer[i * 3 + 1];
byteBufferTemp[i * 4 + 2] = byteBuffer[i * 3 + 2];
byteBufferTemp[i * 4 + 3] = 255;
}
}
let color: ArrayBuffer = byteBufferTemp.buffer as ArrayBuffer;
let opts: image.InitializationOptions = { editable: true, pixelFormat: 3, size: { height: height, width: width } };
let pixelMapTemp: image.PixelMap = image.createPixelMapSync(color, opts);
return pixelMapTemp;
}
@Entry
@Component
struct BppPixelMapPage {
@State pixelMapTemp: image.PixelMap | undefined = undefined;
build() {
Column() {
Image(this.pixelMapTemp)
.objectFit(ImageFit.Contain)
.width('49%')
.height(240);
Button('读取图片')
.width(150)
.onClick(() => {
// 文章图片数据仅作为示例,需要保证传入图片的宽高属性准确,否则会导致崩溃
this.pixelMapTemp = convertBitmapArrayToPixels(buffer.from(imageData).buffer, 787, 1146, 8);
});
}
.height('100%')
.width('100%');
}
}