我目前正在实现一个程序,从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'00000
10000=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.raw
r: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.raw
r: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.raw
r: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.raw
r: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.raw
r: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.raw
r: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
复制相似问题