$ git clone https://librecgm.ion.nu/librecgm.git
commit 779c06506d3af25e2400af64cddc60b7ab1ae52e
Author: Alicia <...>
Date:   Tue Sep 21 00:15:37 2021 +0200

    Some fixes to make readings more accurate/reliable.

diff --git a/gui.c b/gui.c
index 7c9a398..184c2ad 100644
--- a/gui.c
+++ b/gui.c
@@ -74,7 +74,7 @@ static int updatecam(int** onlygrab)
     img.rowstride=gdk_pixbuf_get_rowstride(img_);
     img.pixstride=gdk_pixbuf_get_n_channels(img_);
     memset(img.pixels, 255, img.h*img.rowstride); // Clear to white
-    drawgraph(&img, /*210*/unit*10, 283, list);
+    drawgraph(&img, unit*10, 283, list);
     gtk_image_set_from_pixbuf(display, img_);
     return 0;
   }
diff --git a/read.c b/read.c
index cbb4511..19d98c5 100644
--- a/read.c
+++ b/read.c
@@ -46,7 +46,7 @@ static int scanline(struct img* img, int* line, int max)
     }
     int xrange=(img->w+img->h)/500; // TODO: Scale by (abs(linew)+abs(lineh)) instead
     int yrange=(img->w+img->h)/1000;
-    for(x=0; x<linew; x++)
+    for(x=0; x<abs(linew); x++)
     {
       y=x*lineh/linew;
 //printf("Pixel %i x %i\n", startx+x, starty+y);
@@ -58,6 +58,7 @@ static int scanline(struct img* img, int* line, int max)
         {
           unsigned char* p=pixel(img, line[0]+x+xi, line[1]+y+yi);
           v+=p[0]+p[1]+p[2];
+          v+=abs(p[0]-p[1])+abs(p[1]-p[2])+abs(p[2]-p[0]); // Bonus brightness for colorfulness. The lines we seek are colorless and dark
         }
       }
       if(v<dark){dark=v; darkest=x;}
@@ -74,7 +75,7 @@ static int scanline(struct img* img, int* line, int max)
 //      printf("darkest: %i (~%i mmol/10l)\n", darkest, darkest*210/linew);
       line[2]=line[0]+darkest;
       line[3]=line[1]+darkest*lineh/linew;
-      return darkest*max/linew;
+      return -darkest*max/linew;
     }
   }else{
 //printf("Scanning along Y\n");
@@ -89,7 +90,7 @@ static int scanline(struct img* img, int* line, int max)
     }
     int xrange=(img->w+img->h)/1000; // TODO: Scale by (abs(linew)+abs(lineh)) instead
     int yrange=(img->w+img->h)/500;
-    for(y=0; y<lineh; y++)
+    for(y=0; y<abs(lineh); y++)
     {
       x=y*linew/lineh;
 //printf("Pixel %i x %i\n", startx+x, starty+y);
@@ -101,6 +102,7 @@ static int scanline(struct img* img, int* line, int max)
         {
           unsigned char* p=pixel(img, line[0]+x+xi, line[1]+y+yi);
           v+=p[0]+p[1]+p[2];
+          v+=abs(p[0]-p[1])+abs(p[1]-p[2])+abs(p[2]-p[0]); // Bonus brightness for colorfulness. The lines we seek are colorless and dark
         }
       }
       if(v<dark){dark=v; darkest=y;}
@@ -117,74 +119,103 @@ static int scanline(struct img* img, int* line, int max)
 //      printf("darkest: %i (~%i mmol/10l)\n", darkest, darkest*210/lineh);
       line[2]=line[0]+darkest*linew/lineh;
       line[3]=line[1]+darkest;
-      return darkest*max/lineh;
+      return -darkest*max/lineh;
     }
   }
 }
 
 int* readgraph(struct img* img, int* rect, int max)
 {
+  char debug=0; // TODO: Make togglable from commandline?
   if(!rect){rect=findrect(img);}
   int i;
-/*
-  printf("Rectangle detected:\n");
-  for(i=0; i<4; i++)
+  if(debug)
   {
-    printf("  %i x %i\n", rect[i*2], rect[i*2+1]);
+    printf("Rectangle detected:\n");
+    for(i=0; i<4; i++)
+    {
+      printf("  %i x %i\n", rect[i*2], rect[i*2+1]);
+      drawline(img, &rect[i*2], &rect[((i+1)%4)*2], 0xff0000);
+    }
   }
-*/
   // Find the bluest corner, i.e. the "Ok" button
   int blue=0;
   int tmpblue;
   int bluest;
   for(i=0; i<4; i++)
   {
-//    drawline(img, &rect[i*2], &rect[((i+1)%4)*2], 0xff0000);
     // Find coordinates slightly inset from the corner
     int* a=&rect[i*2];
     int* b=&rect[((i+1)%4)*2];
     int* c=&rect[((i+2)%4)*2];
     int ok[]={(a[0]+b[0]*80+c[0])/82,
               (a[1]+b[1]*80+c[1])/82};
-//    drawline(img, ok, b, 0xff0000);
+    if(debug){drawline(img, ok, b, 0xff0000);}
     int xi,yi;
-    int range=(img->w+img->h)/1000;
+    int range=(img->w+img->h)/200;
     for(yi=-range; yi<range; yi++)
     {
       if(ok[1]+yi<0){continue;}
+      tmpblue=0;
       for(xi=-range; xi<range; xi++)
       {
         if(ok[0]+xi<0){continue;}
         unsigned char* p=pixel(img, ok[0]+xi, ok[1]+yi);
-        if((tmpblue=(p[2]-(p[1]+p[0])/2))>blue){blue=tmpblue; bluest=i+1;}
+        tmpblue+=(p[2]-(p[1]+p[0])/2);
       }
+      if(tmpblue>blue){blue=tmpblue; bluest=(i+1)%4;}
     }
   }
-//  printf("Corner %i appears to have the OK button\n", bluest);
+  if(debug)
+  {
+    printf("Corner %i appears to have the OK button\n", bluest);
+    int* a=&rect[(bluest-1)*2];
+    int* b=&rect[((bluest)%4)*2];
+    int* c=&rect[((bluest+1)%4)*2];
+    int ok[]={(a[0]+b[0]*80+c[0])/82,
+              (a[1]+b[1]*80+c[1])/82};
+    if(debug){drawline(img, ok, b, 0x00ff00);}
+  }
   int right[]={rect[((bluest)%4)*2],
                rect[((bluest)%4)*2+1],
                rect[((bluest+1)%4)*2],
                rect[((bluest+1)%4)*2+1]};
-//  printf("Right: %i x %i  to  %i x %i\n", right[0], right[1], right[2], right[3]);
   int left[]={rect[((bluest+2)%4)*2],
               rect[((bluest+2)%4)*2+1],
               rect[((bluest+3)%4)*2],
               rect[((bluest+3)%4)*2+1]};
-//  printf("Left: %i x %i  to  %i x %i\n", left[0], left[1], left[2], left[3]);
+  if(debug)
+  {
+    printf("Right: %i x %i  to  %i x %i\n", right[0], right[1], right[2], right[3]);
+    printf("Left: %i x %i  to  %i x %i\n", left[0], left[1], left[2], left[3]);
+  }
   #define subline(a,b,p1,p2) {((a)[0]*(p2)+(a)[2]*(p1))/(p1+p2), ((a)[1]*(p2)+(a)[3]*(p1))/(p1+p2),\
                               ((b)[0]*(p1)+(b)[2]*(p2))/(p1+p2), ((b)[1]*(p1)+(b)[3]*(p2))/(p1+p2)}
   int top[]=subline(left, right, 8, 3);
   int bottom[]=subline(right, left, 8, 4);
 //  int header[]=subline(top, bottom, 5, 24);
 //  int end[]=subline(top, bottom, 12, 1);
-//  drawline(img, top, &top[2], 0xff0000);
-//  drawline(img, bottom, &bottom[2], 0xff0000);
+  if(debug)
+  {
+    drawline(img, top, &top[2], 0xff0000);
+    drawline(img, bottom, &bottom[2], 0xff0000);
+  }
   int* list=malloc(sizeof(int)*(12*29-65));
   for(i=65; i<12*29; i++)
   {
     int slice[]=subline(top, bottom, i, 13*29-i);
     list[i-65]=scanline(img, slice, max);
-//    drawline(img, slice, &slice[2], 0xff0000);
+  }
+  if(debug)
+  {
+    for(i=65; i<12*29; i++)
+    {
+      int slice[]=subline(top, bottom, i, 13*29-i);
+      slice[0]=(slice[0]-slice[2])*list[i-65]/max+slice[2];
+      slice[1]=(slice[1]-slice[3])*list[i-65]/max+slice[3];
+      drawline(img, slice, &slice[2], 0xff0000);
+    }
+    writepnm(img, "read.pnm");
   }
   return list;
 }