chiark / gitweb /
does processing, compiles
authorian <ian>
Fri, 22 Oct 2004 21:07:24 +0000 (21:07 +0000)
committerian <ian>
Fri, 22 Oct 2004 21:07:24 +0000 (21:07 +0000)
layout/subseg2display.c

index ae9a139f752a34c0a74a03c32ca00f71c68f8e5f..40122f738cd4e5b6e2d0fade538c6b4c386955d0 100644 (file)
@@ -8,6 +8,7 @@
  *   <idchar><subseg>
  *
  * `..' group is for unspecified segments.
+ * `0.' group is for background.
  *
  * <subseg> is
  *   <segnum>               for fixed track
@@ -33,8 +34,8 @@
 
 /*---------- lookup data structure ----------*/
 
-struct idinfo {
-  double alpha, red, green, blue;
+struct result {
+  double alpha, rgb[3];
 };
 
 typedef unsigned char id;
@@ -48,7 +49,8 @@ struct movperseg {
 #define MAXSEGNUM ((1<<10)-1)
 #define MAXMOVFEATPOS ((1<<6)-1)
 
-static struct idinfo idinfo[NCHARS];
+static struct result idinfo[NCHARS];
+static struct result background;
 
 static id *fixed;
 static int fixed_a;
@@ -87,14 +89,14 @@ static double doublearg(void) {
 /*---------- specification args ----------*/
 
 static void idgroupargs(id ix) {
-  struct idinfo *r;
+  struct result *r;
+  int i;
 
   r= &idinfo[ix];
 
-  r->alpha = doublearg();
-  r->red   = doublearg();
-  r->green = doublearg();
-  r->blue  = doublearg();
+  r->alpha= doublearg();
+  for (i=0; i<3; i++)
+    r->rgb[i]= doublearg();
 }
 
 static void ensure_somethings(void **ary, int *allocd, int want, size_t item,
@@ -134,7 +136,7 @@ ENSURE_THINGS(ids,id);
 ENSURE_THINGS(mps,struct movperseg);
 
 static void subsegarg(id ix, const char *arg) {
-  struct idinfo *r;
+  struct result *r;
   struct movperseg *mps;
   unsigned long segnum, movfeatpos;
   char *ep;
@@ -176,11 +178,98 @@ static void badformat(const char *m) {
   exit(12);
 }
 
+static unsigned reverse_bits_in_byte (unsigned a) {
+  unsigned b, c, d;
+  b= ((a >> 1) & 0x55) | ((a << 1) & 0xaa);
+  c= ((b >> 2) & 0x33) | ((b << 2) & 0xcc);
+  d= ((c >> 4) & 0x0f) | ((c << 4) & 0xf0);
+  return d;
+}
+
+static void angle_to_colour(double result[3],
+                           double angle /* in units of 2pi radians< <1.0 */) {
+  /* Inspired by http://www.acm.org/jgt/papers/SmithLyons96/hsv_rgb.html */
+  int i;
+  double f;
+  
+  angle *= 6.0;
+  i= floor(angle);
+  f= angle - i;
+  
+  if (i&1) f= 1.0 - f;
+
+  switch (i) {
+#define R(r,g,b) if(1){ result[0]=r; result[1]=g; result[2]=b; break; }else
+  case 0: R( 1, f, 0 );
+  case 1: R( f, 1, 0 );
+  case 2: R( 0, 1, f );
+  case 3: R( 0, f, 1 );
+  case 4: R( f, 0, 1 );
+  case 5: R( 1, 0, f );
+#undef R
+  }
+}
+
 static void process(void) {
+  int row, col, i;
+  
   ppm_readppminit(encodingfile, &cols, &rows, &maxval, &informat);
-  if (maxval != 255) badformat("bad maxval");
-  if (informat != RPPM_FORMAT) badformat("bad format");
+  if (maxval != 255) badformat("wrong maxval");
+  if (informat != RPPM_FORMAT) badformat("wrong format");
   ppm_writeppminit(stdout, cols, rows, 255, 0);
+
+  for (row=0; row<rows; row++)
+    for (col=0; col<cols; col++) {
+      unsigned char rgbi[3], rgbo[3];
+      double rgbod[3];
+
+      if (fread(rgbi,1,3,encodingfile)!=-3) {
+       if (ferror(encodingfile)) { perror("reading"); exit(12); }
+       else badformat("truncated file");
+      }
+
+      if (rgbi[0]==255 && rgbi[1]==255 && rgbi[2]==255) {
+
+       for (i=0; i<3; i++)
+         rgbod[i]= background.rgb[i];
+       
+      } else {
+       int segnum, movfeatpos, red, blue, green, ix;
+       double rgbdirn[3], angle;
+       struct result *r;
+
+       red= rgbi[0];
+       green= reverse_bits_in_byte(rgbi[1]);
+       blue= reverse_bits_in_byte(rgbi[2]);
+      
+       if (red & 0x03) badformat("reserved bits set in red");
+       angle= ((red >> 2) & 0x3f) / 64.0;
+
+       segnum= blue | ((green & 0xc0) << 2);
+       movfeatpos= green & 0x3f;
+
+       assert(segnum <= MAXSEGNUM);
+       assert(movfeatpos <= MAXMOVFEATPOS);
+
+       angle_to_colour(rgbdirn, angle);
+
+       ix= !movfeatpos ?
+         (segnum < fixed_a ? fixed[segnum] : fixed[0]) :
+         (segnum < moveable_a && movfeatpos < moveable[segnum].lookup_a
+          ? moveable[segnum].lookup[movfeatpos] : fixed[0]);
+
+       r= &idinfo[ix];
+
+       for (i=0; i<3; i++)
+         rgbod[i]= r->alpha * rgbdirn[i] + (1.0 - r->alpha) * r->rgb[i];
+
+      }
+
+      for (i=0; i<3; i++)
+       rgbo[i]= rgbod[i] * 255.0;
+
+      if (fwrite(rgbi,1,3,stdout)!=3) { perror("writing"); exit(12); }
+    }
 }
 
 int main(int argc_spec, char **argv_spec) {