DEV Community

codemee
codemee

Posted on

RGB565 轉 RGB888

在使用 MaixPy 時, 攝影機的格式通常會設為 RGB565, 這個模式會用 5+6+5 共 16 個 bits 表示顏色:

R:5   G:6   B:5
←高位元   低位元→
Enter fullscreen mode Exit fullscreen mode

MaixPy 中的 image 物件可以使用 to_bytes() 取得內部使用的 bytesarray 物件 (和 OpenMV 中的 bytearray() 類似), 即可存取個別像素的 RGB565 顏色值。如果想從 bytearray 中更改像素值, 每一個像素值就是 2 個位元組, 高位元組在前, 所以如果想要取得影像中最開頭的像素的 RGB 值, 可以這樣做:

img = sensor.snapshot()
bi = img.to_bytes()
r5 = (bi[0] & 0xF8) >> 3
g6 = ((bi[0] & 0x07) << 3) | ((bi[1] & 0xE0)>>5)
b5 = bi[1] & 0x1F
Enter fullscreen mode Exit fullscreen mode

即可取得以 5、6、5 個 bits 個別表示的 RGB 值。

如果想將這樣的 RGB565 顏色值轉換成 RGB 各用 8 個 bits 表示的 RGB888 格式, 可以這樣做:

r8 = r5 << 3
g8 = g6 << 2
b8 = b5 << 3
Enter fullscreen mode Exit fullscreen mode

這是單純將 r5、b5 從 0~31 的範圍轉換到 0~255 範圍、g6 從 0~63 的範圍轉換到 0~255 範圍的快速算法。不過如果只是這樣簡單的轉換, 會遇到一個問題, 以白色來舉例, RGB565 的白色是:

0x11111 111111 11111
Enter fullscreen mode Exit fullscreen mode

用上述方式轉換成 RGB888 會變成:

R8: 0b11111000
G8: 0b11111100
B8: 0b11111000
Enter fullscreen mode Exit fullscreen mode

你可以發現這不是真正的白色, 在 ARM 開發者網站 上建議我們在轉換後的數值尾端填上高位處的 bits, 例如:

r8 = (r5 << 3) | (r5 >> 2)
g8 = (g6 << 2) | (g6 >> 4)
b8 = (b5 << 3) | (b5 >> 2)
Enter fullscreen mode Exit fullscreen mode

這樣的作法可以讓接近上限的 RGB565 值在轉換成 RGB888 時用高位元來補償低位元, 避免發生顏色的損失。

Top comments (2)

Collapse
 
greatxiang profile image
大相

我来自中国大陆,也在使用maixpy,你解决了困扰了我很多天的问题,谢谢

Collapse
 
codemee profile image
codemee

很高興能幫上忙