Source code of Windows XP (NT5)
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.

255 lines
7.3 KiB

  1. /*
  2. * win8map.c - program to create an 8 bit RGB color map for OpenGL use
  3. *
  4. * OpenGL RGB rendering needs to know red, green, & blue component bit
  5. * sizes and positions. On 8 bit palette devices you need to create a
  6. * logical palette that has the correct RGB values for all 256 possible
  7. * entries. This program will create an 8 bit RGB color cube with a
  8. * default gamma of 1.4.
  9. *
  10. * Unfortunately, if you select this palette into an 8 bit display DC, you
  11. * will not realize all of the logical palette. This is because the standard
  12. * 20 colors in the system palette cannot be changed. This program changes
  13. * some of the entries in the logical palette to match enties in the system
  14. * palette. The program does a least squares calculation to find the
  15. * enties to replace.
  16. *
  17. *
  18. *
  19. * Note: Three bits for red & green, two for blue, red is lsb, blue msb
  20. */
  21. #include <stdio.h>
  22. #include <math.h>
  23. #define DEFAULT_GAMMA 1.4F
  24. #define MAX_PAL_ERROR (3*256*256L)
  25. struct colorentry {
  26. unsigned char red;
  27. unsigned char green;
  28. unsigned char blue;
  29. };
  30. struct rampentry {
  31. struct colorentry color;
  32. long defaultindex;
  33. unsigned char flags;
  34. };
  35. struct defaultentry {
  36. struct colorentry color;
  37. long rampindex;
  38. unsigned char flags;
  39. };
  40. /* values for flags */
  41. #define EXACTMATCH 0x01
  42. #define CHANGED 0x02 /* one of the default entries is close */
  43. /*
  44. * These arrays hold bit arrays with a gamma of 1.0
  45. * used to convert n bit values to 8 bit values
  46. */
  47. unsigned char threeto8[8] = {
  48. 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
  49. };
  50. unsigned char twoto8[4] = {
  51. 0, 0x55, 0xaa, 0xff
  52. };
  53. unsigned char oneto8[2] = {
  54. 0, 255
  55. };
  56. struct defaultentry defaultpal[20] = {
  57. { 0, 0, 0 },
  58. { 0x80,0, 0 },
  59. { 0, 0x80,0 },
  60. { 0x80,0x80,0 },
  61. { 0, 0, 0x80 },
  62. { 0x80,0, 0x80 },
  63. { 0, 0x80,0x80 },
  64. { 0xC0,0xC0,0xC0 },
  65. { 192, 220, 192 },
  66. { 166, 202, 240 },
  67. { 255, 251, 240 },
  68. { 160, 160, 164 },
  69. { 0x80,0x80,0x80 },
  70. { 0xFF,0, 0 },
  71. { 0, 0xFF,0 },
  72. { 0xFF,0xFF,0 },
  73. { 0, 0, 0xFF },
  74. { 0xFF,0, 0xFF },
  75. { 0, 0xFF,0xFF },
  76. { 0xFF,0xFF,0xFF }
  77. };
  78. struct rampentry rampmap[256];
  79. void
  80. gammacorrect(double gamma)
  81. {
  82. int i;
  83. unsigned char v, nv;
  84. double dv;
  85. for (i=0; i<8; i++) {
  86. v = threeto8[i];
  87. dv = (255.0 * pow(v/255.0, 1.0/gamma)) + 0.5;
  88. nv = (unsigned char)dv;
  89. printf("Gamma correct %d to %d (gamma %.2f)\n", v, nv, gamma);
  90. threeto8[i] = nv;
  91. }
  92. for (i=0; i<4; i++) {
  93. v = twoto8[i];
  94. dv = (255.0 * pow(v/255.0, 1.0/gamma)) + 0.5;
  95. nv = (unsigned char)dv;
  96. printf("Gamma correct %d to %d (gamma %.2f)\n", v, nv, gamma);
  97. twoto8[i] = nv;
  98. }
  99. printf("\n");
  100. }
  101. main(int argc, char *argv[])
  102. {
  103. long i, j, error, min_error;
  104. long error_index, delta;
  105. double gamma;
  106. struct colorentry *pc;
  107. if (argc == 2)
  108. gamma = atof(argv[1]);
  109. else
  110. gamma = DEFAULT_GAMMA;
  111. gammacorrect(gamma);
  112. /* First create a 256 entry RGB color cube */
  113. for (i = 0; i < 256; i++) {
  114. /* BGR: 2:3:3 */
  115. rampmap[i].color.red = threeto8[(i&7)];
  116. rampmap[i].color.green = threeto8[((i>>3)&7)];
  117. rampmap[i].color.blue = twoto8[(i>>6)&3];
  118. }
  119. /* Go through the default palette and find exact matches */
  120. for (i=0; i<20; i++) {
  121. for(j=0; j<256; j++) {
  122. if ( (defaultpal[i].color.red == rampmap[j].color.red) &&
  123. (defaultpal[i].color.green == rampmap[j].color.green) &&
  124. (defaultpal[i].color.blue == rampmap[j].color.blue)) {
  125. rampmap[j].flags = EXACTMATCH;
  126. rampmap[j].defaultindex = i;
  127. defaultpal[i].rampindex = j;
  128. defaultpal[i].flags = EXACTMATCH;
  129. break;
  130. }
  131. }
  132. }
  133. /* Now find close matches */
  134. for (i=0; i<20; i++) {
  135. if (defaultpal[i].flags == EXACTMATCH)
  136. continue; /* skip entries w/ exact matches */
  137. min_error = MAX_PAL_ERROR;
  138. /* Loop through RGB ramp and calculate least square error */
  139. /* if an entry has already been used, skip it */
  140. for(j=0; j<256; j++) {
  141. if (rampmap[j].flags != 0) /* Already used */
  142. continue;
  143. delta = defaultpal[i].color.red - rampmap[j].color.red;
  144. error = (delta * delta);
  145. delta = defaultpal[i].color.green - rampmap[j].color.green;
  146. error += (delta * delta);
  147. delta = defaultpal[i].color.blue - rampmap[j].color.blue;
  148. error += (delta * delta);
  149. if (error < min_error) { /* New minimum? */
  150. error_index = j;
  151. min_error = error;
  152. }
  153. }
  154. defaultpal[i].rampindex = error_index;
  155. rampmap[error_index].flags = CHANGED;
  156. rampmap[error_index].defaultindex = i;
  157. }
  158. /* First print out the color cube */
  159. printf("Standard 8 bit RGB color cube with gamma %.2f:\n", gamma);
  160. for (i=0; i<256; i++) {
  161. pc = &rampmap[i].color;
  162. printf("%3ld: (%3d, %3d, %3d)\n", i, pc->red, pc->green, pc->blue);
  163. }
  164. printf("\n");
  165. /* Now print out the default entries that have an exact match */
  166. for (i=0; i<20; i++) {
  167. if (defaultpal[i].flags == EXACTMATCH) {
  168. pc = &defaultpal[i].color;
  169. printf("Default entry %2ld exactly matched RGB ramp entry %3ld",
  170. i, defaultpal[i].rampindex);
  171. printf(" (%3d, %3d, %3d)\n", pc->red, pc->green, pc->blue);
  172. }
  173. }
  174. printf("\n");
  175. /* Now print out the closet entries for rest of the default entries */
  176. for (i=0; i<20; i++) {
  177. if (defaultpal[i].flags != EXACTMATCH) {
  178. pc = &defaultpal[i].color;
  179. printf("Default entry %2ld (%3d, %3d, %3d) is close to ",
  180. i, pc->red, pc->green, pc->blue);
  181. pc = &rampmap[defaultpal[i].rampindex].color;
  182. printf("RGB ramp entry %3ld (%3d, %3d, %3d)\n",
  183. defaultpal[i].rampindex, pc->red, pc->green, pc->blue);
  184. }
  185. }
  186. printf("\n");
  187. /* Print out code to initialize a logical palette that will not overflow */
  188. printf("Here is code you can use to create a logical palette\n");
  189. printf("static struct {\n");
  190. printf(" WORD palVersion;\n");
  191. printf(" WORD palNumEntries;\n");
  192. printf(" PALETTEENTRY palPalEntries[256];\n");
  193. printf("} rgb8palette = {\n");
  194. printf(" 0x300,\n");
  195. printf(" 256,\n");
  196. for (i=0; i<256; i++) {
  197. if (rampmap[i].flags == 0)
  198. pc = &rampmap[i].color;
  199. else
  200. pc = &defaultpal[rampmap[i].defaultindex].color;
  201. printf(" %3d, %3d, %3d, 0, /* %ld",
  202. pc->red, pc->green, pc->blue, i);
  203. if (rampmap[i].flags == EXACTMATCH)
  204. printf(" - Exact match with default %d", rampmap[i].defaultindex);
  205. if (rampmap[i].flags == CHANGED)
  206. printf(" - Changed to match default %d", rampmap[i].defaultindex);
  207. printf(" */\n");
  208. }
  209. printf("};\n");
  210. printf("\n * * *\n\n");
  211. printf(" hpal = CreatePalette((LOGPALETTE *)&rgb8palette);\n");
  212. return 0;
  213. }