chiark / gitweb /
Reverse order of samples in Rgb and other optimisations
[ypp-sc-tools.main.git] / pctb / structure.c
index 8ab74ee3ced0e94f6dfe990557447e40efc574da..21bb1697e19e68c10788980546fc80ba58b7bded 100644 (file)
@@ -67,7 +67,7 @@ void select_page(int page) {
 
 
 typedef struct {
-  Rgb rgb; /* on screen */
+  Rgb rgbx; /* on screen, REVERSED BYTES ie r||g||b */
   char c; /* canonical */
 } CanonColourInfo;
 
@@ -114,9 +114,9 @@ CanonColourInfoReds canoncolourinfo_tree;
 void canon_colour_prepare(void) {
   const CanonColourInfo *cci;
   for (cci=canoncolourinfo_table; cci->c; cci++) {
-    unsigned char r= cci->rgb >> 16;
-    unsigned char g= cci->rgb >>  8;
-    unsigned char b= cci->rgb;
+    unsigned char r= cci->rgbx >> 16;
+    unsigned char g= cci->rgbx >>  8;
+    unsigned char b= cci->rgbx;
 
     CanonColourInfoGreens *greens= canoncolourinfo_tree.red2[r];
     if (!greens) {
@@ -170,7 +170,7 @@ static void mustfail2(void) {
 #define MP(v) fprintf(stderr," %s=%d,%d",#v,(v).x,(v).y)
 #define MI(v) fprintf(stderr," %s=%d",   #v,(v))
 #define MIL(v) fprintf(stderr," %s=%ld", #v,(v))
-#define MRGB(v) fprintf(stderr," %s=%06lx", #v,(v))
+#define MRGB(v) fprintf(stderr," %s=%06"PRIx32, #v,(v))
 #define MC(v) fprintf(stderr," %s='%c'", #v,(v))
 #define MS(v) fprintf(stderr," %s=\"%s\"", #v,(v))
 #define MF(v) fprintf(stderr," %s=%f", #v,(v))
@@ -491,10 +491,10 @@ static void file_read_image_ppm(FILE *f) {
   struct pam inpam;
   unsigned char rgb_buf[3];
   CanonImage *im;
-  RgbImage *rgb;
+  RgbImage *ri;
   PageStruct *pstruct;
 
-  progress("page %d reading...",npages);
+  progress("page %d reading       ...",npages);
 
   pnm_readpaminit(f, &inpam, sizeof(inpam));
   if (!(inpam.maxval == 255 &&
@@ -502,14 +502,12 @@ static void file_read_image_ppm(FILE *f) {
        inpam.format == RPPM_FORMAT))
     fatal("PNM screenshot(s) file must be 8bpp 1 byte-per-sample RGB raw");
 
-  CANONICALISE_IMAGE(im, inpam.width, inpam.height, rgb, {
-    int rr= fread(&rgb_buf,1,3,f);
-    sysassert(!ferror(f));
+  CANONICALISE_IMAGE(im, inpam.width, inpam.height, ri, {
+    errno=0; int rr= fread_unlocked(&rgb_buf,1,3,f);
+    sysassert(rr==3);
     if (rr!=3) fatal("PNM screenshot(s) file ends unexpectedly");
 
-    r= rgb_buf[0];
-    g= rgb_buf[1];
-    b= rgb_buf[2];
+    rgb= rgb_buf[0] | (rgb_buf[1] << 8) | (rgb_buf[2] << 16);
   });
 
   sysassert(!ferror(screenshot_file));
@@ -518,15 +516,15 @@ static void file_read_image_ppm(FILE *f) {
     fatal("Too many images in screenshots file; max is %d.\n", MAX_PAGES);
 
   find_structure(im,&pstruct, 0,0,0,0);
-  store_current_page(im,pstruct,rgb);
+  store_current_page(im,pstruct,ri);
   npages++;
 }
 
 void store_current_page(CanonImage *ci, PageStruct *pstruct, RgbImage *rgb) {
   assert(ci==cim);
-  progress("page %d condensing...",npages);
+  progress("page %d unantialiasing...",npages);
   adjust_colours(ci, rgb);
-  progress("page %d storing...",npages);
+  progress("page %d storing       ...",npages);
   if (!npages) page0_rgbimage= rgb;
   else free(rgb);
   page_images[npages]= cim;
@@ -536,6 +534,7 @@ void store_current_page(CanonImage *ci, PageStruct *pstruct, RgbImage *rgb) {
 
 void read_one_screenshot(void) {
   progress("reading screenshot...");
+  file_read_image_ppm(screenshot_file);
   progress_log("read screenshot.");
 }
 
@@ -559,40 +558,54 @@ void read_screenshots(void) {
   progress_log("read %d screenshots.",npages);
 }
 
-static inline double find_aa_density(const RgbImage *ri,
-                                    Point p, long background,
-                                    long foreground, int fg_extra) {
+static double aa_bg_chan[3], aa_scale_chan[3], aa_alpha_mean_max;
+static Rgb aa_background, aa_foreground;
+
+static void find_aa_density_prep(Rgb bg, Rgb fg, int fg_extra) {
+  int i;
+  unsigned char fg_chan[3];
+
+  aa_background= bg;
+  aa_foreground= fg;
+  aa_alpha_mean_max= fg_extra ? 0.999 : 1.0;
+
+  for (i=0; i<3; i++) {
+    aa_bg_chan[i]=             (aa_background >> (i*8)) & 0xff;
+    fg_chan[i]=                 aa_foreground >> (i*8);
+    aa_scale_chan[i]= 1.0 / (fg_chan[i] + fg_extra - aa_bg_chan[i]);
+  }
+}
+
+static inline double find_aa_density(const RgbImage *ri, Point p) {
   Rgb here= ri_rgb(ri, p.x, p.y);
 
-  double alpha[3], alpha_mean=0;
+  double alpha[3], alpha_total=0;
   int i;
   for (i=0; i<3; i++) {
-    unsigned char here_chan= here       >> (i*8);
-    unsigned char bg_chan=   background >> (i*8);
-    unsigned char fg_chan=   foreground >> (i*8);
-    double alpha_chan=
-      ((double)here_chan    - (double)bg_chan) /
-      ((fg_chan + fg_extra) - (double)bg_chan);
+    unsigned char here_chan= here >> (i*8);
+
+    double alpha_chan= (here_chan - aa_bg_chan[i]) * aa_scale_chan[i];
     alpha[i]= alpha_chan;
-    alpha_mean += alpha_chan * (1/3.0);
+    alpha_total += alpha_chan;
   }
 
+  double alpha_mean= round(alpha_total * (1e5/3.0)) * 1e-5;
+  
   double thresh= 1.5/AAMAXVAL;
   double alpha_min= alpha_mean - thresh;
   double alpha_max= alpha_mean + thresh;
+
   for (i=0; i<3; i++)
     MUST( alpha_min <= alpha[i] && alpha[i] <= alpha_max,
          MP(p);
-         MRGB(here);MRGB(background);MRGB(foreground);MI(fg_extra);
+         MRGB(here);MRGB(aa_background);MRGB(aa_foreground);
+         MF(aa_alpha_mean_max);
          MF(alpha_min); MI(i);MF(alpha[i]);MF(alpha_max) );
 
-  if (   -1e-5 <  alpha_mean && alpha_mean <= 0.0     ) alpha_mean= 0.0;
-  if (1.0      <= alpha_mean && alpha_mean <= 1.0+1e-5) alpha_mean= 1.0;
-
-  MUST( 0 <= alpha_mean &&
-       (fg_extra ? (alpha_mean < 0.999) : (alpha_mean <= 1.0)),
+  MUST( 0 <= alpha_mean && alpha_mean <= aa_alpha_mean_max,
        MP(p);
-       MRGB(here);MRGB(background);MRGB(foreground);MI(fg_extra);
+       MRGB(here);MRGB(aa_background);MRGB(aa_foreground);
+       MF(aa_alpha_mean_max);
        MF(alpha_mean); MF(alpha[0]);MF(alpha[1]);MF(alpha[2]); );
 
   return alpha_mean;
@@ -672,19 +685,24 @@ static void adjust_colours_cell(CanonImage *ci, const RgbImage *ri,
   Rgb background;
   unsigned char chanbg[3];
   long bg_count=0, light_count=0, dark_count=0;
+  int i;
   Point p;
 
   background= ri_rgb(ri, cell.br.x, cell.br.y);
-  memcpy(chanbg, RI_PIXEL(ri, cell.br.x, cell.br.y), 3);
+  for (i=0; i<3; i++)
+    chanbg[i]= background >> (i*8);
 
   FOR_P_RECT(p,cell) {
-    const unsigned char *here_pixel= RI_PIXEL(ri, p.x, p.y);
-    int i;
-    for (i=0; i<3; i++) {
-      unsigned here= here_pixel[i];
-      if (here == chanbg[i]) bg_count++;
-      else if (here < chanbg[i]) dark_count  += (chanbg[i] - here)/4 + 1;
-      else if (here > chanbg[i]) light_count += (here - chanbg[i])/4 + 1;
+    Rgb herergb= ri_rgb(ri, p.x, p.y);
+    if (herergb==background) {
+      bg_count+=3;
+    } else {
+      for (i=0; i<3; i++) {
+       unsigned char here= herergb >> (i*8);
+       if (here == chanbg[i]) bg_count++;
+       else if (here < chanbg[i]) dark_count  += (chanbg[i] - here)/4 + 1;
+       else if (here > chanbg[i]) light_count += (here - chanbg[i])/4 + 1;
+      }
     }
   }
   long total_count= RECT_W(cell) * RECT_H(cell) * 3;
@@ -717,8 +735,10 @@ static void adjust_colours_cell(CanonImage *ci, const RgbImage *ri,
 
   int monochrome= 1;
 
+  find_aa_density_prep(background, foreground, fg_extra);
+
   FOR_P_RECT(p,cell) {
-    double alpha= find_aa_density(ri,p,background,foreground,fg_extra);
+    double alpha= find_aa_density(ri,p);
 
     int here_int= floor((AAMAXVAL+1)*alpha);
     assert(here_int <= AAMAXVAL);
@@ -754,7 +774,7 @@ void analyse(FILE *tsv_output) {
     if (!rd)
       rd= ocr_init(text_h);
 
-    progress("Scanning page %d...",page);
+    progress("Processing page %d...",page);
 
     const char *tab= "";
     
@@ -812,14 +832,14 @@ void find_islandname(void) {
   Rect sunshiner= find_sunshine_widget();
   char sunshine[MAXIMGIDENT], archisland[MAXIMGIDENT];
 
-  const unsigned char *srcp;
-  unsigned char *destp, *endp;
+  const Rgb *srcp;
+  Rgb *destp, *endp;
   for (srcp= rgbsrc->data, destp=ri->data,
-        endp= ri->data + 3 * ri->w * ri->h;
+        endp= ri->data + ri->w * ri->h;
        destp < endp;
        srcp++, destp++) {
-    unsigned char c= *srcp & 0xf0;
-    *destp= c | (c>>4);
+    Rgb new= *srcp & 0xf0f0f0;
+    *destp= new | (new>>4);
   }
 
   identify_rgbimage(ri, sunshiner, sunshine, "sunshine widget");
@@ -845,13 +865,11 @@ void find_islandname(void) {
 //    islandnamer.br.y = larger_islandnamebry;
     debug_rect("islandnamer",1, islandnamer);
 
-    int x,y,i;
+    int x,y;
     for (x=islandnamer.tl.x; x<=islandnamer.br.x; x++)
       for (y=islandnamer.tl.y; y<=islandnamer.br.y; y++) {
-       if (RI_PIXEL(ri,x,y)[0] < 0x40) {
-         for (i=0; i<3; i++) {
-           RI_PIXEL(ri,x,y)[i]= 0;
-         }
+       if ((ri_rgb(ri,x,y) & 0xff) < 0x40) {
+         *RI_PIXEL32(ri,x,y)= 0;
        }
       }
 
@@ -904,10 +922,12 @@ void find_islandname(void) {
       uint32_t pattern=0;
       int runs[32], nruns=0;
       runs[0]=0; runs[1]=0;
+
+      find_aa_density_prep(0xCCCCAA,0x002255,0);
       
       for (p.y=islandnamer.tl.y; p.y<=islandnamer.br.y; p.y++) {
        pattern <<= 1;
-       double alpha= find_aa_density(ri,p, 0xCCCCAA,0x002255,0);
+       double alpha= find_aa_density(ri,p);
        if (alpha >= 0.49) {
           runs[nruns]++;
           pattern |= 1u;