ref: f57df708538093ffb47727a522a0217b9ee81125
dir: /sys/src/cmd/getmap.c/
#include <u.h> #include <libc.h> #include <draw.h> /* * int getcmap(int id, char *file, unsigned char *buf) * Read a colormap from the given file into the buffer. * Returns 1 on success, 0 otherwise. * Goes to unglaublich length to figure out what the file name means: * If the name is "screen" or "display" or "vga", reads the colormap from /dev/draw/id/colormap. * If the name is "gamma",returns gamma=2.3 colormap * If the name is "gamma###", returns gamma=#### colormap * Ditto for rgamma, for reverse video. * Looks for the file in a list of directories (given below). */ char *cmapdir[] = { "", "/lib/cmap/", 0 }; int getcmap(int id, char *f, unsigned char *buf) { char name[512]; char *s, *lines[256], *fields[4]; int cmap, i, j, n, v, rev; double gamma; cmap = -1; for(i=0; cmapdir[i]!=nil ;i++){ snprint(name, sizeof name, "%s%s", cmapdir[i], f); if((cmap = open(name, OREAD)) >= 0) break; } if(cmap == -1){ if(strcmp(name, "screen")==0 || strcmp(name, "display")==0 || strcmp(name, "vga")==0){ snprint(name, sizeof name, "/dev/draw/%d/colormap", id); cmap = open(name, OREAD); if(cmap < 0) return 0; } } if(cmap==-1){ /* could be gamma or gamma<number> or fb */ if(strncmp(f, "gamma", 5)==0){ rev=0; f+=5; }else if(strncmp(f, "rgamma", 6)==0){ rev = 1; f+=6; }else return 0; if(*f == '\0') gamma=2.3; else{ if(strspn(f, "0123456789.") != strlen(f)) return 0; gamma = atof(f); } for(i=0; i!=256; i++){ v=255.*pow(i/255., 1./gamma); if(rev) v=255-v; buf[0] = buf[1] = buf[2] = v; buf += 3; } return 1; } s = malloc(20000); n = readn(cmap, s, 20000-1); if(n <= 0) return 0; s[n] = '\0'; if(getfields(s, lines, 256, 0, "\n") != 256) return 0; for(i=0; i<256; i++){ if(getfields(lines[i], fields, 4, 1, " \t") != 4) return 0; if(atoi(fields[0]) != i) return 0; for(j=0; j<3; j++) buf[3*i+j] = atoi(fields[j+1]); } return 1; } /* replicate (from top) value in v (n bits) until it fills a ulong */ ulong rep(ulong v, int n) { int o; ulong rv; rv = 0; for(o=32-n; o>=0; o-=n) rv |= v<<o; if(o != -n) rv |= v>>-o; return rv; } void putcmap(int id, uchar cmap[256*3]) { char *s, *t; int i, fd; char name[64]; snprint(name, sizeof name, "/dev/draw/%d/colormap", id); fd = open(name, OWRITE); if(fd < 0) sysfatal("can't open colormap file: %r"); s = malloc(20000); t = s; for(i = 0; i<256; i++) t += sprint(t, "%d %d %d %d\n", i, cmap[3*i+0], cmap[3*i+1], cmap[3*i+2]); if(write(fd, s, t-s) != t-s) sysfatal("writing color map: %r"); close(fd); } void main(int argc, char *argv[]) { uchar cmapbuf[256*3]; char *map, buf[12*12+1]; int fd, id; if(argc>2){ fprint(2, "usage: %s colormap\n", argv[0]); exits("usage"); } map = "rgbv"; if(argc > 1) map = argv[1]; fd = open("/dev/draw/new", OREAD); if(fd < 0 || read(fd, buf, sizeof buf) != 12*12) sysfatal("can't connect to display: %r"); id = atoi(buf+0*12); if(strncmp(buf+2*12, " m8 ", 12) != 0) sysfatal("can't set colormap except on CMAP8 (m8) displays; this one is %.12s", buf+2*12); if(getcmap(id, map, cmapbuf) == 0){ fprint(2, "%s: can't find %s\n", argv[0], map); exits("not found"); } putcmap(id, cmapbuf); exits(0); }