You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.7 KiB
140 lines
4.7 KiB
/**************************************************************************\
|
|
*
|
|
* Copyright (c) 1999-2000 Microsoft Corporation
|
|
*
|
|
* Module name:
|
|
*
|
|
* sRGB <-> sRGB64 color conversion
|
|
*
|
|
* Abstract:
|
|
*
|
|
* Converts colors between the sRGB and sRGB64 color spaces.
|
|
*
|
|
* Notes:
|
|
*
|
|
* !!![agodfrey]
|
|
* For sRGB64->sRGB, we just clamp out-of-range components to [0,255].
|
|
* We may need to provide the option of doing something more sophisticated.
|
|
*
|
|
* Revision History:
|
|
*
|
|
* 06/09/1999 agodfrey
|
|
* Created it.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hpp"
|
|
|
|
namespace sRGB
|
|
{
|
|
BYTE UnlinLookup(INT16 input);
|
|
}
|
|
|
|
// UnlinearizeLUT, UnlinearizeLUT2: Lookup tables used to convert from
|
|
// sRGB64 to sRGB.
|
|
//
|
|
// The first table maps the high byte of the input to the smallest possible
|
|
// corresponding output.
|
|
//
|
|
// The second table describes, for each output, the maximum input which
|
|
// produces that output. The algorithm uses the first table to find an
|
|
// approximate answer, then scans the second table to find the exact result.
|
|
|
|
static BYTE UnlinearizeLUT[32] =
|
|
{
|
|
0x0, 0x31, 0x47, 0x56, 0x63, 0x6e, 0x78, 0x81,
|
|
0x89, 0x91, 0x98, 0x9e, 0xa5, 0xab, 0xb1, 0xb6,
|
|
0xbc, 0xc1, 0xc6, 0xca, 0xcf, 0xd4, 0xd8, 0xdc,
|
|
0xe1, 0xe5, 0xe9, 0xed, 0xf0, 0xf4, 0xf8, 0xfb,
|
|
};
|
|
|
|
static INT16 UnlinearizeLUT2[256] =
|
|
{
|
|
0x1, 0x3, 0x6, 0x8, 0xb, 0xd, 0x10, 0x12,
|
|
0x15, 0x17, 0x1a, 0x1c, 0x1f, 0x22, 0x25, 0x28,
|
|
0x2c, 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x48,
|
|
0x4d, 0x52, 0x57, 0x5c, 0x61, 0x67, 0x6d, 0x73,
|
|
0x79, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
|
|
0xb1, 0xb9, 0xc1, 0xca, 0xd2, 0xdb, 0xe4, 0xed,
|
|
0xf6, 0x100, 0x10a, 0x114, 0x11e, 0x128, 0x133, 0x13e,
|
|
0x149, 0x154, 0x160, 0x16c, 0x178, 0x184, 0x190, 0x19d,
|
|
0x1aa, 0x1b7, 0x1c5, 0x1d2, 0x1e0, 0x1ee, 0x1fc, 0x20b,
|
|
0x21a, 0x229, 0x238, 0x248, 0x257, 0x268, 0x278, 0x288,
|
|
0x299, 0x2aa, 0x2bb, 0x2cd, 0x2df, 0x2f1, 0x303, 0x316,
|
|
0x328, 0x33b, 0x34f, 0x362, 0x376, 0x38a, 0x39f, 0x3b3,
|
|
0x3c8, 0x3dd, 0x3f3, 0x409, 0x41e, 0x435, 0x44b, 0x462,
|
|
0x479, 0x490, 0x4a8, 0x4c0, 0x4d8, 0x4f1, 0x509, 0x522,
|
|
0x53c, 0x555, 0x56f, 0x589, 0x5a3, 0x5be, 0x5d9, 0x5f4,
|
|
0x610, 0x62c, 0x648, 0x664, 0x681, 0x69e, 0x6bb, 0x6d9,
|
|
0x6f7, 0x715, 0x733, 0x752, 0x771, 0x791, 0x7b0, 0x7d0,
|
|
0x7f1, 0x811, 0x832, 0x853, 0x875, 0x896, 0x8b8, 0x8db,
|
|
0x8fe, 0x921, 0x944, 0x968, 0x98b, 0x9b0, 0x9d4, 0x9f9,
|
|
0xa1e, 0xa44, 0xa6a, 0xa90, 0xab6, 0xadd, 0xb04, 0xb2b,
|
|
0xb53, 0xb7b, 0xba4, 0xbcc, 0xbf5, 0xc1f, 0xc48, 0xc72,
|
|
0xc9c, 0xcc7, 0xcf2, 0xd1d, 0xd49, 0xd75, 0xda1, 0xdce,
|
|
0xdfb, 0xe28, 0xe55, 0xe83, 0xeb2, 0xee0, 0xf0f, 0xf3e,
|
|
0xf6e, 0xf9e, 0xfce, 0xfff, 0x1030, 0x1061, 0x1093, 0x10c5,
|
|
0x10f7, 0x1129, 0x115c, 0x1190, 0x11c3, 0x11f7, 0x122c, 0x1261,
|
|
0x1296, 0x12cb, 0x1301, 0x1337, 0x136d, 0x13a4, 0x13db, 0x1413,
|
|
0x144b, 0x1483, 0x14bb, 0x14f4, 0x152e, 0x1567, 0x15a1, 0x15dc,
|
|
0x1616, 0x1651, 0x168d, 0x16c8, 0x1705, 0x1741, 0x177e, 0x17bb,
|
|
0x17f9, 0x1837, 0x1875, 0x18b4, 0x18f3, 0x1932, 0x1972, 0x19b2,
|
|
0x19f2, 0x1a33, 0x1a74, 0x1ab6, 0x1af8, 0x1b3a, 0x1b7d, 0x1bc0,
|
|
0x1c04, 0x1c47, 0x1c8c, 0x1cd0, 0x1d15, 0x1d5a, 0x1da0, 0x1de6,
|
|
0x1e2c, 0x1e73, 0x1eba, 0x1f02, 0x1f4a, 0x1f92, 0x1fdb, 0x7fff,
|
|
};
|
|
|
|
// Method of unlinearizing using a lookup table
|
|
//
|
|
// This has two steps - first, we use the high byte of the input
|
|
// to get an approximate answer for the output (using UnlinearizeLUT).
|
|
//
|
|
// Then we scan UnlinearizeLUT2 to find the exact answer.
|
|
// The i'th entry of UnlinearizeLUT2 is the highest input which will map
|
|
// to i.
|
|
|
|
BYTE
|
|
sRGB::UnlinLookup(
|
|
INT16 input
|
|
)
|
|
{
|
|
BYTE temp = UnlinearizeLUT[(input & 0xff00)>>8];
|
|
INT16 *lutPtr = &UnlinearizeLUT2[temp];
|
|
|
|
while (*lutPtr < input)
|
|
{
|
|
temp++;
|
|
lutPtr++;
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
// CLAMP64: Map inputs below 0 to 0, above SRGB_ONE to 255,
|
|
// and in between to the given expression.
|
|
|
|
#define CLAMP64(input, expr) (((input) <= 0) ? 0 : \
|
|
(((input) >= SRGB_ONE) ? 255 : \
|
|
(expr)))
|
|
|
|
ARGB
|
|
sRGB::ConvertTosRGB(
|
|
ARGB64 color
|
|
)
|
|
{
|
|
sRGBColor result;
|
|
sRGB64Color c;
|
|
|
|
c.argb = color;
|
|
|
|
// [agodfrey] The compiler generates an IMUL for the multiply by 255,
|
|
// and I can't get it to use a MUL instead. Oh well, it's probably
|
|
// insignificant.
|
|
|
|
result.a = CLAMP64(c.a, (c.a * 255) >> SRGB_FRACTIONBITS);
|
|
result.r = CLAMP64(c.r, UnlinLookup(c.r));
|
|
result.g = CLAMP64(c.g, UnlinLookup(c.g));
|
|
result.b = CLAMP64(c.b, UnlinLookup(c.b));
|
|
|
|
return result.argb;
|
|
}
|
|
|