getmap.c 3.2 KB

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