我目前正在实现一个程序,从BMP文件中读取和解码图像。但我真的对像素格式感到困惑,尤其是对比特的痴迷。
我目前的理解是,当提到像素格式时,例如RGBA32,我们是用人类的方式来表示它,即使用大端字节,因此第一个字节是R,第二个G,第三个B,第四个A:
RGBA32
11111111 22222222 33333333 44444444
R G B A在此格式(如RGBA32BE/RGBA32LE,)中添加大/小端点时,这将相应地更改字节顺序,如下所示:
RGBA32BE (unchanged)
11111111 22222222 33333333 44444444
R G B A
RGBA32LE (reversed)
11111111 22222222 33333333 44444444
A B G R这一切在我看来都很自然,只要我们假设每个组件的单个值就是我们读取的字节的值。
然而,当组件大小小于1字节或8位时,我开始感到困惑。假设是RGB555BE,我想下面是如何将其表示为字节数组的:
RGB555BE
1'22222'33 333'44444
A R G B
0'00001'00 000'0000010000=16还是00001=1?发布于 2022-03-01 12:37:45
我们可以使用FFmpeg测试不同的像素格式。
结论是:
uint16)时,endianness是相关的。
uint16元素的字节顺序是: LSB,MSB。
位端点:uint16元素的字节顺序是: MSB,LSB。执行FFmpeg CLI命令进行测试:
例如,从rgb24开始:
ffmpeg -y -lavfi color=red:size=8x8:rate=1:duration=1 -pix_fmt rgb24 -f rawvideo red.raw
ffmpeg -y -lavfi color=0x00FF00:size=8x8:rate=1:duration=1 -pix_fmt rgb24 -f rawvideo green.raw
ffmpeg -y -lavfi color=blue:size=8x8:rate=1:duration=1 -pix_fmt rgb24 -f rawvideo blue.raw使用像HxD这样的十六进制查看器来检查原始文件内容。
red.raw FF 00 00 FF 00 00...
blue.raw 00 FF 00 00 FF 00...
green.raw 00 00 FF 00 00 FF...
rgba像素格式:
ffmpeg -y -lavfi color=red:size=8x8:rate=1:duration=1 -pix_fmt rgba -f rawvideo red.raw
ffmpeg -y -lavfi color=0x00FF00:size=8x8:rate=1:duration=1 -pix_fmt rgba -f rawvideo green.raw
ffmpeg -y -lavfi color=blue:size=8x8:rate=1:duration=1 -pix_fmt rgba -f rawvideo blue.rawr:FF 00 00 FF
g:00 FF 00 FF
b:00 00 FF FF
FFmpeg约定是字节的顺序。
我们不能说命名是否适用于很少或大的endian。
在使用uint16组件(而不是uint8组件)时,endianness是相关的。
rgba像素格式:
ffmpeg -y -lavfi color=red:size=8x8:rate=1:duration=1 -pix_fmt rgba -f rawvideo red.raw
ffmpeg -y -lavfi color=0x00FF00:size=8x8:rate=1:duration=1 -pix_fmt rgba -f rawvideo green.raw
ffmpeg -y -lavfi color=blue:size=8x8:rate=1:duration=1 -pix_fmt rgba -f rawvideo blue.rawr:FF 00 00 FF
g:00 FF 00 FF
b:00 00 FF FF
A,R,G,B,A.
我们可以称rgba为RGBA32BE,但这太让人困惑了.
rgb555le像素格式:
ffmpeg -y -lavfi color=red:size=8x8:rate=1:duration=1 -pix_fmt rgb555le -f rawvideo red.raw
ffmpeg -y -lavfi color=0x00FF00:size=8x8:rate=1:duration=1 -pix_fmt rgb555le -f rawvideo green.raw
ffmpeg -y -lavfi color=blue:size=8x8:rate=1:duration=1 -pix_fmt rgb555le -f rawvideo blue.rawr:00 7C 00 7C
g:E0 03 E0 03
b:1F 00 1F 00
我们还可以检查较低的位(关于位的排序):
将颜色设置为8,因此在移动后值为1。
ffmpeg -y -lavfi color=0x000008:size=8x8:rate=1:duration=1 -pix_fmt rgb555le -f rawvideo red.raw
ffmpeg -y -lavfi color=0x000800:size=8x8:rate=1:duration=1 -pix_fmt rgb555le -f rawvideo green.raw
ffmpeg -y -lavfi color=0x080000:size=8x8:rate=1:duration=1 -pix_fmt rgb555le -f rawvideo blue.rawr:01 00 01 00 2字节(以位为单位):00000001 00000000
g:20 00 20 00 2字节(位):00100000 00000000
b:00 04 00 04 2字节(以位为单位):00000000 00000100
rgb555be像素格式:
ffmpeg -y -lavfi color=red:size=8x8:rate=1:duration=1 -pix_fmt rgb555be -f rawvideo red.raw
ffmpeg -y -lavfi color=0x00FF00:size=8x8:rate=1:duration=1 -pix_fmt rgb555be -f rawvideo green.raw
ffmpeg -y -lavfi color=blue:size=8x8:rate=1:duration=1 -pix_fmt rgb555be -f rawvideo blue.rawr:7C 00 7C 00
g:03 E0 03 E0
b:00 1F 00 1F
检查下位(查看位序):
ffmpeg -y -lavfi color=0x000008:size=8x8:rate=1:duration=1 -pix_fmt rgb555be -f rawvideo red.raw
ffmpeg -y -lavfi color=0x000800:size=8x8:rate=1:duration=1 -pix_fmt rgb555be -f rawvideo green.raw
ffmpeg -y -lavfi color=0x080000:size=8x8:rate=1:duration=1 -pix_fmt rgb555be -f rawvideo blue.rawr:00 01 00 01
g:00 20 00 20
b:04 00 04 00
在大端字节格式中,只交换字节。
(对于每个uint16元素(两个字节),交换第一个和第二个字节的顺序)。
问题的答案:
10000=16还是00001=1 ?的形式读取R组件答案:
rgb555le:00000001 00000000
rgb555be:00000000 00000001
答案:
在像素格式的上下文中,没有“位endianness”,只有“字节endianness”。
Bits与串行通信更相关,从软件角度看,我们看不到每个字节中位的顺序。
答案:
RGB555LE (as RGB555LE_v1):
byte0 byte1
gggbbbbb 0rrrrrgg
(大多数左位是每个字节中的上位)。
我们最好将数据看作一个uint16元素:
b:0000000000011111 (纯蓝色)
g:0000001111100000 (纯绿色)
r:0111110000000000 (纯红色)
我们可以把它看作是uint16:0rrrrrgggggbbbbb
发布于 2022-03-01 01:24:24
我认为endianness对rgb555并不重要,这就是为什么您的链接将rgb555、rgb555le和rgb555be捆绑在一起的原因。因此,使用rgba的示例也不敏感,因为它的组件都是<= 8位。
至于rgb555是如何以2字节(嗯,15位)表示的,您可以在FFmpeg回购中搜索rgb555,看看编码器/解码器是如何处理这种像素格式的。这是我找到的第138行
static uint16_t rgb24_to_rgb555(uint8_t *rgb24)
{
uint16_t rgb555 = 0;
uint32_t r, g, b;
r = rgb24[0] >> 3;
g = rgb24[1] >> 3;
b = rgb24[2] >> 3;
rgb555 |= (r << 10);
rgb555 |= (g << 5);
rgb555 |= (b << 0);
return rgb555;
}编码器采用rgb555 (16位无符号int ),a使用put_bits()实用程序函数将这15位推送到其比特流,如第683项所示。
put_bits(&s->pb, 16, rgb24_to_rgb555(avg_color));下面是指向bits.h的链接
https://stackoverflow.com/questions/71302279
复制相似问题