簡體   English   中英

將 16 位顏色轉換為 32 位

[英]Convert 16bit colour to 32bit

我有一個 16 位位圖圖像,每種顏色表示為一個短(2 個字節),我需要在 32 位位圖上下文中顯示它。 如何在 C++ 中將 2 字節顏色轉換為 4 字節顏色?

輸入格式在單個短(2 個字節)中包含每種顏色。

輸出格式為 32 位 RGB。 這意味着我相信每個像素有 3 個字節?

我需要將短值轉換為 RGB 顏色。

請原諒我對顏色的了解不足,這是我第一次進入圖形編程世界。

通常一個 16 位像素是 5 位紅色、6 位綠色和 5 位藍色數據。 最小誤差解決方案(即,保證輸出顏色與輸入顏色最接近)是:

red8bit   = (red5bit << 3) | (red5bit >> 2);
green8bit = (green6bit << 2) | (green6bit >> 4);
blue8bit  = (blue5bit << 3) | (blue5bit >> 2);

要了解此解決方案為何有效,讓我們看一下紅色像素。 我們的 5 位紅色是某個分數fivebit/31 我們想把它轉換成一個新的分數eightbit/255 一些簡單的算術:

     fivebit   eightbit
     ------- = --------
        31        255

產量:

     eightbit = fivebit * 8.226

或者接近(注意波浪線 ≈):

     eightbit ≈ (fivebit * 8) + (fivebit * 0.25)

該操作是乘以 8 和除以 4。Owch - 這兩個操作可能會在您的硬件上永遠運行。 幸運的是,它們都是 2 的冪,可以轉換為移位操作:

     eightbit = (fivebit << 3) | (fivebit >> 2);

相同的步驟適用於每像素 6 位的綠色,但您當然會得到相應不同的答案! 記住解決方案的快速方法是您從“短”像素中取出最高位並將它們添加到底部以制作“長”像素。 此方法同樣適用於您需要映射到更高分辨率空間的任何數據集。 幾個快速示例:

    five bit space         eight bit space        error
    00000                  00000000                 0%
    11111                  11111111                 0%
    10101                  10101010                0.02%
    00111                  00111001               -1.01%

常見的格式包括 BGR0、RGB0、0RGB、0BGR。 在下面的代碼中,我假設了 0RGB。 改變這很容易,只需修改最后一行中的移位量。

unsigned long rgb16_to_rgb32(unsigned short a)
{
/* 1. Extract the red, green and blue values */

/* from rrrr rggg gggb bbbb */
unsigned long r = (a & 0xF800) >11;
unsigned long g = (a & 0x07E0) >5;
unsigned long b = (a & 0x001F);

/* 2. Convert them to 0-255 range:
There is more than one way. You can just shift them left:
to 00000000 rrrrr000 gggggg00 bbbbb000
r <<= 3;
g <<= 2;
b <<= 3;
But that means your image will be slightly dark and
off-colour as white 0xFFFF will convert to F8,FC,F8
So instead you can scale by multiply and divide: */

r = r * 255 / 31;
g = g * 255 / 63;
b = b * 255 / 31;
/* This ensures 31/31 converts to 255/255 */

/* 3. Construct your 32-bit format (this is 0RGB): */
return (r << 16) | (g << 8) | b;

/* Or for BGR0:
return (r << 8) | (g << 16) | (b << 24);
*/
}

將三個(四個,當你有一個 alpha 層)值乘以 16 - 就是這樣:)

您有 16 位顏色並希望將其設為 32 位顏色。 這為您提供了四乘以四位,您希望將其轉換為四乘以八位。 您正在添加四位,但您應該將它們添加到值的右側。 為此,將它們移位 4 位(乘以 16)。 此外,您可以通過添加 8 來補償不准確度(您添加了 4 位,其值為 0-15,您可以取 8 的平均值來補償)

更新這僅適用於每個通道使用 4 位並具有 Alpha 通道的顏色。

我在這里打多久,但我實際上有與ARGB顏色相同的問題,而是和沒有一個答案是真正正確的:請記住,這個答案讓我們想這樣做一個稍微不同的情況的響應轉換:

AAAARRRRGGGGBBBB >>= AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB

如果您想保持相同的顏色比例,您只需進行交叉乘法:您想將 0 到 15 之間的值x轉換為 0 到 255 之間的值:因此您想要: y = 255 * x / 15

然而,255 = 15 * 17,它本身就是 16 + 1:你現在有y = 16 * x + x這實際上與對位向左移動然后再次添加值(或更直觀,復制值: 0b1101變為0b11011101 )。

現在你有了這個,你可以通過執行以下操作來計算你的整數:

  a = v & 0b1111000000000000
  r = v & 0b111100000000
  g = v & 0b11110000
  b = v & 0b1111
  return b | b << 4 | g << 4 | g << 8 | r << 8 | r << 12 | a << 12 | a << 16

此外,由於較低的位不會對最終顏色產生太大影響,而且如果不需要精確,您只需將每個分量乘以 16 即可獲得一些性能:

  return b << 4 | g << 8 | r << 12 | a << 16

(所有的左移值都很奇怪,因為我們之前沒有費心做右移)

有一些關於模型的問題,比如它是 HSV 還是 RGB? 如果你想准備好,開火,瞄准,我會先試試這個。

#include <stdint.h>

uint32_t convert(uint16_t _pixel) 
{
    uint32_t pixel;
    pixel = (uint32_t)_pixel;
    return ((pixel & 0xF000) << 16)
         | ((pixel & 0x0F00) << 12)
         | ((pixel & 0x00F0) << 8)
         | ((pixel & 0x000F) << 4);
}

這會映射 0xRGBA -> 0xRRGGBBAA,或者可能是 0xHSVA -> 0xHHSSVVAA,但它不會映射 0xHSVA -> 0xRRGGBBAA。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM