Leaked source code of windows server 2003
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

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999-2000 Microsoft Corporation
  4. *
  5. * Module name:
  6. *
  7. * sRGB <-> sRGB64 color conversion
  8. *
  9. * Abstract:
  10. *
  11. * Converts colors between the sRGB and sRGB64 color spaces.
  12. *
  13. * Notes:
  14. *
  15. * !!![agodfrey]
  16. * For sRGB64->sRGB, we just clamp out-of-range components to [0,255].
  17. * We may need to provide the option of doing something more sophisticated.
  18. *
  19. * Revision History:
  20. *
  21. * 06/09/1999 agodfrey
  22. * Created it.
  23. *
  24. \**************************************************************************/
  25. #include "precomp.hpp"
  26. namespace sRGB
  27. {
  28. BYTE UnlinLookup(INT16 input);
  29. }
  30. // UnlinearizeLUT, UnlinearizeLUT2: Lookup tables used to convert from
  31. // sRGB64 to sRGB.
  32. //
  33. // The first table maps the high byte of the input to the smallest possible
  34. // corresponding output.
  35. //
  36. // The second table describes, for each output, the maximum input which
  37. // produces that output. The algorithm uses the first table to find an
  38. // approximate answer, then scans the second table to find the exact result.
  39. static BYTE UnlinearizeLUT[32] =
  40. {
  41. 0x0, 0x31, 0x47, 0x56, 0x63, 0x6e, 0x78, 0x81,
  42. 0x89, 0x91, 0x98, 0x9e, 0xa5, 0xab, 0xb1, 0xb6,
  43. 0xbc, 0xc1, 0xc6, 0xca, 0xcf, 0xd4, 0xd8, 0xdc,
  44. 0xe1, 0xe5, 0xe9, 0xed, 0xf0, 0xf4, 0xf8, 0xfb,
  45. };
  46. static INT16 UnlinearizeLUT2[256] =
  47. {
  48. 0x1, 0x3, 0x6, 0x8, 0xb, 0xd, 0x10, 0x12,
  49. 0x15, 0x17, 0x1a, 0x1c, 0x1f, 0x22, 0x25, 0x28,
  50. 0x2c, 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x48,
  51. 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x67, 0x6d, 0x73,
  52. 0x79, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
  53. 0xb1, 0xb9, 0xc1, 0xca, 0xd2, 0xdb, 0xe4, 0xed,
  54. 0xf6, 0x100, 0x10a, 0x114, 0x11e, 0x128, 0x133, 0x13e,
  55. 0x149, 0x154, 0x160, 0x16c, 0x178, 0x184, 0x190, 0x19d,
  56. 0x1aa, 0x1b7, 0x1c5, 0x1d2, 0x1e0, 0x1ee, 0x1fc, 0x20b,
  57. 0x21a, 0x229, 0x238, 0x248, 0x257, 0x268, 0x278, 0x288,
  58. 0x299, 0x2aa, 0x2bb, 0x2cd, 0x2df, 0x2f1, 0x303, 0x316,
  59. 0x328, 0x33b, 0x34f, 0x362, 0x376, 0x38a, 0x39f, 0x3b3,
  60. 0x3c8, 0x3dd, 0x3f3, 0x409, 0x41e, 0x435, 0x44b, 0x462,
  61. 0x479, 0x490, 0x4a8, 0x4c0, 0x4d8, 0x4f1, 0x509, 0x522,
  62. 0x53c, 0x555, 0x56f, 0x589, 0x5a3, 0x5be, 0x5d9, 0x5f4,
  63. 0x610, 0x62c, 0x648, 0x664, 0x681, 0x69e, 0x6bb, 0x6d9,
  64. 0x6f7, 0x715, 0x733, 0x752, 0x771, 0x791, 0x7b0, 0x7d0,
  65. 0x7f1, 0x811, 0x832, 0x853, 0x875, 0x896, 0x8b8, 0x8db,
  66. 0x8fe, 0x921, 0x944, 0x968, 0x98b, 0x9b0, 0x9d4, 0x9f9,
  67. 0xa1e, 0xa44, 0xa6a, 0xa90, 0xab6, 0xadd, 0xb04, 0xb2b,
  68. 0xb53, 0xb7b, 0xba4, 0xbcc, 0xbf5, 0xc1f, 0xc48, 0xc72,
  69. 0xc9c, 0xcc7, 0xcf2, 0xd1d, 0xd49, 0xd75, 0xda1, 0xdce,
  70. 0xdfb, 0xe28, 0xe55, 0xe83, 0xeb2, 0xee0, 0xf0f, 0xf3e,
  71. 0xf6e, 0xf9e, 0xfce, 0xfff, 0x1030, 0x1061, 0x1093, 0x10c5,
  72. 0x10f7, 0x1129, 0x115c, 0x1190, 0x11c3, 0x11f7, 0x122c, 0x1261,
  73. 0x1296, 0x12cb, 0x1301, 0x1337, 0x136d, 0x13a4, 0x13db, 0x1413,
  74. 0x144b, 0x1483, 0x14bb, 0x14f4, 0x152e, 0x1567, 0x15a1, 0x15dc,
  75. 0x1616, 0x1651, 0x168d, 0x16c8, 0x1705, 0x1741, 0x177e, 0x17bb,
  76. 0x17f9, 0x1837, 0x1875, 0x18b4, 0x18f3, 0x1932, 0x1972, 0x19b2,
  77. 0x19f2, 0x1a33, 0x1a74, 0x1ab6, 0x1af8, 0x1b3a, 0x1b7d, 0x1bc0,
  78. 0x1c04, 0x1c47, 0x1c8c, 0x1cd0, 0x1d15, 0x1d5a, 0x1da0, 0x1de6,
  79. 0x1e2c, 0x1e73, 0x1eba, 0x1f02, 0x1f4a, 0x1f92, 0x1fdb, 0x7fff,
  80. };
  81. // Method of unlinearizing using a lookup table
  82. //
  83. // This has two steps - first, we use the high byte of the input
  84. // to get an approximate answer for the output (using UnlinearizeLUT).
  85. //
  86. // Then we scan UnlinearizeLUT2 to find the exact answer.
  87. // The i'th entry of UnlinearizeLUT2 is the highest input which will map
  88. // to i.
  89. BYTE
  90. sRGB::UnlinLookup(
  91. INT16 input
  92. )
  93. {
  94. BYTE temp = UnlinearizeLUT[(input & 0xff00)>>8];
  95. INT16 *lutPtr = &UnlinearizeLUT2[temp];
  96. while (*lutPtr < input)
  97. {
  98. temp++;
  99. lutPtr++;
  100. }
  101. return temp;
  102. }
  103. // CLAMP64: Map inputs below 0 to 0, above SRGB_ONE to 255,
  104. // and in between to the given expression.
  105. #define CLAMP64(input, expr) (((input) <= 0) ? 0 : \
  106. (((input) >= SRGB_ONE) ? 255 : \
  107. (expr)))
  108. ARGB
  109. sRGB::ConvertTosRGB(
  110. ARGB64 color
  111. )
  112. {
  113. sRGBColor result;
  114. sRGB64Color c;
  115. c.argb = color;
  116. // [agodfrey] The compiler generates an IMUL for the multiply by 255,
  117. // and I can't get it to use a MUL instead. Oh well, it's probably
  118. // insignificant.
  119. result.a = CLAMP64(c.a, (c.a * 255) >> SRGB_FRACTIONBITS);
  120. result.r = CLAMP64(c.r, UnlinLookup(c.r));
  121. result.g = CLAMP64(c.g, UnlinLookup(c.g));
  122. result.b = CLAMP64(c.b, UnlinLookup(c.b));
  123. return result.argb;
  124. }