我目前正在實作一個程式來讀取和解碼 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
我們將 R 分量讀為
10000=16or00001=1嗎?我更困惑的是我們讀取組件的方式(位位元組序)是否與位元組位元組序有關?
RGB555LE格式在位元組陣列中的表示方式是什么?
RGB555LE_v1 333'44444 1'22222'33 G" B A R G' 000'00000 0'00001'00 or RGB555LE_v2 ? 44444'333 33'22222'1 B G R A 00000'000 00'10000'0
uj5u.com熱心網友回復:
我們可以使用 FFmpeg 來測驗不同的像素格式。
結論是:
- 沒有位位元組序,只有位元組位元組序。
- 當基本元素為 2 個位元組 (
uint16) 時,位元組序是相關的。Little endian:元素的
位元組順序為:[LSB,MSB]。Bit endian:元素的 位元組順序為:[MSB, LSB]。uint16uint16
執行 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 約定位元組的順序。
我們不能說命名是應用小端還是大端。
使用uint16組件(不是uint8組件)時,位元組序是相關的。
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 then R then G then B then A...
We may refer rgba as RGBA32BE, but it's too confusing...
rgb555le pixel format:
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
We may also check the lower bit (for bits ordering):
Set the color to 8 so after shifting the value be 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 bytes in bits: 00000001 00000000
g: 20 00 20 00 2 bytes in bits: 00100000 00000000
b: 00 04 00 04 2 bytes in bits: 00000000 00000100
rgb555be pixel format:
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
Checking the lower bit (for bits ordering):
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
In big endian format, only the bytes are swapped.
(For every uint16 element (two bytes), order of the first and second byte is swapped).
Answers to questions:
- Do we read the R component as
10000=16or00001=1 ?
Answer:
For rgb555le: 00000001 00000000
For rgb555be: 00000000 00000001
- I'm even more confused about if the way we read the component (bit endianness) is related to byte endianness?
Answer:
In context of pixel format, there is no "bit endianness" there is only "byte endianness".
Bits endianness is more relevant to serial communication, from software perspective, we don't see the order of bits in each byte.
- Which way is RGB555LE format represented in byte array?
Answer:
RGB555LE (as RGB555LE_v1):
byte0 byte1
gggbbbbb 0rrrrrgg
(most left bit is the upper bit in each byte).
We better look at the data as one uint16 element:
b: 0000000000011111 (pure blue)
g: 0000001111100000 (pure green)
r: 0111110000000000 (pure red)
We may look at it as uint16 as: 0rrrrrgggggbbbbb
uj5u.com熱心網友回復:
我不認為位元組序對 , 很重要rgb555,這就是為什么你的鏈接將rgb555,rgb555le和rgb555be在一起。就此而言,您的示例rgba也不是位元組序敏感的,因為它的組件都是 <= 8 位。
至于如何rgb555以 2 個位元組(嗯,15 位)表示,您可以搜索 FFmpeg存盤庫rgb555并查看編碼器/解碼器如何處理這種像素格式。這是我找到的rpzaenc.c第 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;
}
編碼器采用rgb55516 位無符號整數,并使用put_bits() 實用函式將這 15 位推送到其位元流,如第 683 行所示
put_bits(&s->pb, 16, rgb24_to_rgb555(avg_color));
這是put_bits.h的鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/435950.html
上一篇:在畫廊幻燈片中隱藏額外的影像
