2

RGB888 24ビットから16ビットRGB565に変換するルーチンの結果、変換が行われるたびに色が徐々に暗くなることに気付きました...式は次のように線形補間を使用します...

typedef struct _RGB24 RGB24;
struct _RGB24 {
   BYTE B;
   BYTE G;
   BYTE R;
};

RGB24 *s; // source
WORD *d; // destination
WORD r;
WORD g;
WORD b;

// Code to convert from 24-bit to 16 bit
r = (WORD)((double)(s[x].r * 31) / 255.0);
g = (WORD)((double)(s[x].g * 63) / 255.0);
b = (WORD)((double)(s[x].b * 31) / 255.0);
d[x] = (r << REDSHIFT) | (g << GREENSHIFT) | (b << BLUESHIFT);

// Code to convert from 16-bit to 24-bit
s[x].r = (BYTE)((double)(((d[x] & REDMASK) >> REDSHIFT) * 255) / 31.0);
s[x].g = (BYTE)((double)(((d[x] & GREENMASK) >> GREENSHIFT) * 255) / 63.0);
s[x].b = (BYTE)((double)(((d[x] & BLUEMASK) >> BLUESHIFT) * 255) / 31.0);

16ビットから24ビットへの変換は似ていますが、逆補間を使用します...逆の場合、色が方程式を循環するたびに値がどんどん低くなっていく方法がわかりません...元々はそこにありますダブルへのキャストはありませんでしたが、浮動小数点除算を行うとフォールオフが発生しないと考えました...しかし、それでも...

4

5 に答える 5

3

double値をWORDに変換すると、値が切り捨てられます。たとえば、(126 * 31)/ 255 = 15.439、これは15に切り捨てられます。値は切り捨てられるため、反復ごとに徐々に低くなります。丸めを導入する必要があります(整数に変換する前に計算値に0.5を加算することにより)

例を続けると、15を取り、次のように変換し直します。(15 * 255)/ 31 = 123.387これは、123に切り捨てられます。

于 2010-11-09T06:24:38.327 に答える
3

このような単純なものには浮動小数点を使用しないでください。私が見た通常の方法は、ダウンコンバージョンでは切り捨てますが、アップコンバージョンでは拡張します(したがって、0b11111は0b11111111になります)。

// Code to convert from 24-bit to 16 bit
r = s[x].r >> (8-REDBITS);
g = s[x].g >> (8-GREENBITS);
b = s[x].b >> (8-BLUEBITS);
d[x] = (r << REDSHIFT) | (g << GREENSHIFT) | (b << BLUESHIFT);

// Code to convert from 16-bit to 24-bit
s[x].r = (d[x] & REDMASK) >> REDSHIFT;                        // 000abcde
s[x].r = s[x].r << (8-REDBITS) | s[x].r >> (2*REDBITS-8);     // abcdeabc
s[x].g = (d[x] & GREENMASK) >> GREENSHIFT;                    // 00abcdef
s[x].g = s[x].g << (8-GREENBITS) | s[x].g >> (2*GREENBITS-8); // abcdefab
s[x].b = (d[x] & BLUEMASK) >> BLUESHIFT;                      // 000abcde
s[x].b = s[x].b << (8-BLUEBITS) | s[x].b >> (2*BLUEBITS-8);   // abcdeabc
于 2011-03-23T11:40:29.313 に答える
1

にキャストすると、値は丸めdoubleられWORDませんdouble。小数点以下が切り捨てられます。丸め動作を取得するには、ある種の丸めルーチンを使用する必要があります。通常、半分を均等に丸めます。必要に応じてC++で丸める方法に関するスタックオーバーフローの質問があります


また、24ビットから16ビットに変換すると、情報が完全に失われることに注意してください。もちろん、24ビットの情報を16ビットに収めることは不可能です。16ビットから24ビットに変換して元に戻すことはできません。

于 2010-11-09T06:20:04.080 に答える
0

これは、16ビットが2を掛けた値(たとえば2 * 2 * 2 * 2)で機能し、rrggbbとして出力され、同じ32ビットの場合はビット値全体に2を掛けるからです。

つまり、16ビット24ビット32ビットは、rgbと2の乗算で機能し、値を色で表示します。
簡単に言うと、ビットカラーの概念を見つける必要があります。ウィキペディアでチェックして、お役に立てば幸いです。

于 2010-11-20T07:04:12.990 に答える
0

とにかくdoubleに変換しているので、少なくともオーバーフローを回避するためにそれを使用します。つまり、置換します。

r = (WORD)((double)(s[x].r * 31) / 255.0);

r = (WORD)round(s[x].r / 255.0 * 31.0); 

このようにして、コンパイラーは31.0/255.0をコストのかかるものに折りたたむ必要があります。

明らかに、これを大量のピクセルに対して繰り返す必要がある場合は、代わりにLUT(ルックアップテーブル)を作成して使用することをお勧めします。

于 2011-01-12T17:37:36.693 に答える