getmap.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. /*
  13. * int getcmap(int id, char *file, unsigned char *buf)
  14. * Read a colormap from the given file into the buffer.
  15. * Returns 1 on success, 0 otherwise.
  16. * Goes to unglaublich length to figure out what the file name means:
  17. * If the name is "screen" or "display" or "vga", reads the colormap from /dev/draw/id/colormap.
  18. * If the name is "gamma",returns gamma=2.3 colormap
  19. * If the name is "gamma###", returns gamma=#### colormap
  20. * Ditto for rgamma, for reverse video.
  21. * Looks for the file in a list of directories (given below).
  22. */
  23. char *cmapdir[] = {
  24. "",
  25. "/lib/cmap/",
  26. 0
  27. };
  28. int
  29. getcmap(int id, char *f, unsigned char *buf)
  30. {
  31. char name[512];
  32. char *s, *lines[256], *fields[4];
  33. int cmap, i, j, n, v, rev;
  34. double gamma;
  35. cmap = -1;
  36. for(i=0; cmapdir[i]!=nil ;i++){
  37. snprint(name, sizeof name, "%s%s", cmapdir[i], f);
  38. if((cmap = open(name, OREAD)) >= 0)
  39. break;
  40. }
  41. if(cmap == -1){
  42. if(strcmp(name, "screen")==0 || strcmp(name, "display")==0 || strcmp(name, "vga")==0){
  43. snprint(name, sizeof name, "/dev/draw/%d/colormap", id);
  44. cmap = open(name, OREAD);
  45. if(cmap < 0)
  46. return 0;
  47. }
  48. }
  49. if(cmap==-1){ /* could be gamma or gamma<number> or fb */
  50. if(strncmp(f, "gamma", 5)==0){
  51. rev=0;
  52. f+=5;
  53. }else if(strncmp(f, "rgamma", 6)==0){
  54. rev = 1;
  55. f+=6;
  56. }else
  57. return 0;
  58. if(*f == '\0')
  59. gamma=2.3;
  60. else{
  61. if(strspn(f, "0123456789.") != strlen(f))
  62. return 0;
  63. gamma = atof(f);
  64. }
  65. for(i=0; i!=256; i++){
  66. v=255.*pow(i/255., 1./gamma);
  67. if(rev)
  68. v=255-v;
  69. buf[0] = buf[1] = buf[2] = v;
  70. buf += 3;
  71. }
  72. return 1;
  73. }
  74. s = malloc(20000);
  75. n = readn(cmap, s, 20000-1);
  76. if(n <= 0)
  77. return 0;
  78. s[n] = '\0';
  79. if(getfields(s, lines, 256, 0, "\n") != 256)
  80. return 0;
  81. for(i=0; i<256; i++){
  82. if(getfields(lines[i], fields, 4, 1, " \t") != 4)
  83. return 0;
  84. if(atoi(fields[0]) != i)
  85. return 0;
  86. for(j=0; j<3; j++)
  87. buf[3*i+j] = atoi(fields[j+1]);
  88. }
  89. return 1;
  90. }
  91. /* replicate (from top) value in v (n bits) until it fills a uint32_t */
  92. uint32_t
  93. rep(uint32_t v, int n)
  94. {
  95. int o;
  96. uint32_t rv;
  97. rv = 0;
  98. for(o=32-n; o>=0; o-=n)
  99. rv |= v<<o;
  100. if(o != -n)
  101. rv |= v>>-o;
  102. return rv;
  103. }
  104. void
  105. putcmap(int id, uint8_t cmap[256*3])
  106. {
  107. char *s, *t;
  108. int i, fd;
  109. char name[64];
  110. snprint(name, sizeof name, "/dev/draw/%d/colormap", id);
  111. fd = open(name, OWRITE);
  112. if(fd < 0)
  113. sysfatal("can't open colormap file: %r");
  114. s = malloc(20000);
  115. t = s;
  116. for(i = 0; i<256; i++)
  117. t += sprint(t, "%d %d %d %d\n", i, cmap[3*i+0], cmap[3*i+1], cmap[3*i+2]);
  118. if(write(fd, s, t-s) != t-s)
  119. sysfatal("writing color map: %r");
  120. close(fd);
  121. }
  122. void
  123. main(int argc, char *argv[])
  124. {
  125. uint8_t cmapbuf[256*3];
  126. char *map, buf[12*12+1];
  127. int fd, id;
  128. if(argc>2){
  129. fprint(2, "Usage: %s colormap\n", argv[0]);
  130. exits("usage");
  131. }
  132. map = "rgbv";
  133. if(argc > 1)
  134. map = argv[1];
  135. fd = open("/dev/draw/new", OREAD);
  136. if(fd < 0 || read(fd, buf, sizeof buf) != 12*12)
  137. sysfatal("can't connect to display: %r");
  138. id = atoi(buf+0*12);
  139. if(strncmp(buf+2*12, " m8 ", 12) != 0)
  140. sysfatal("can't set colormap except on CMAP8 (m8) displays; this one is %.12s", buf+2*12);
  141. if(getcmap(id, map, cmapbuf) == 0){
  142. fprint(2, "%s: can't find %s\n", argv[0], map);
  143. exits("not found");
  144. }
  145. putcmap(id, cmapbuf);
  146. exits(0);
  147. }