typedef struct {
- Rgb rgb; /* on screen */
+ Rgb rgbx; /* on screen, REVERSED BYTES ie r||g||b */
char c; /* canonical */
} CanonColourInfo;
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) {
#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))
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 &&
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));
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;
void read_one_screenshot(void) {
progress("reading screenshot...");
+ file_read_image_ppm(screenshot_file);
progress_log("read screenshot.");
}
progress_log("read %d screenshots.",npages);
}
-static inline double find_aa_density(const RgbImage *ri,
- Point p, long background,
- long foreground, int fg_extra) {
+#define FIXPT_SHIFT 15
+
+typedef long Fixpt;
+static inline Fixpt int2fixpt(int x) { return x<<FIXPT_SHIFT; }
+static inline Fixpt dbl2fixpt(double x) { return x * int2fixpt(1); }
+static inline double fixpt2dbl(Fixpt x) { return x / (1.0*int2fixpt(1)); }
+static inline Fixpt fixpt_mul(Fixpt a, Fixpt b) {
+ return (a*b + dbl2fixpt(0.5)) >> FIXPT_SHIFT;
+}
+#define MFP(v) fprintf(stderr," %s=%lx=%f", #v,(v),fixpt2dbl((v)))
+
+static Fixpt 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 ? int2fixpt(1)-1 : int2fixpt(1);
+
+ for (i=0; i<3; i++) {
+ aa_bg_chan[i]= int2fixpt( (aa_background >> (i*8)) & 0xff );
+ fg_chan[i]= aa_foreground >> (i*8);
+
+ aa_scale_chan[i]= 1.0 / (int2fixpt(fg_chan[i]) + fg_extra - aa_bg_chan[i])
+ * dbl2fixpt(1) * dbl2fixpt(1);
+ }
+}
+
+static inline Fixpt find_aa_density(const RgbImage *ri, Point p) {
Rgb here= ri_rgb(ri, p.x, p.y);
- double alpha[3], alpha_mean=0;
+ if (here==aa_background) return 0;
+
+ Fixpt 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);
+
+ Fixpt alpha_chan= fixpt_mul(int2fixpt(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 thresh= 1.5/AAMAXVAL;
- double alpha_min= alpha_mean - thresh;
- double alpha_max= alpha_mean + thresh;
+ Fixpt one_third= dbl2fixpt(1/3.0);
+ Fixpt alpha_mean= fixpt_mul(alpha_total, one_third);
+
+ Fixpt thresh= dbl2fixpt(1.5/AAMAXVAL);
+ Fixpt alpha_min= alpha_mean - thresh;
+ Fixpt 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);
- 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;
+ MRGB(here);MRGB(aa_background);MRGB(aa_foreground);
+ MFP(aa_alpha_mean_max);
+ MFP(alpha_min); MI(i);MFP(alpha[i]);MFP(alpha_max) );
- 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);
- MF(alpha_mean); MF(alpha[0]);MF(alpha[1]);MF(alpha[2]); );
+ MRGB(here);MRGB(aa_background);MRGB(aa_foreground);
+ MFP(aa_alpha_mean_max);
+ MFP(alpha_mean); MFP(alpha[0]);MFP(alpha[1]);MFP(alpha[2]); );
return alpha_mean;
}
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;
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);
+ Fixpt alpha= find_aa_density(ri,p);
- int here_int= floor((AAMAXVAL+1)*alpha);
+ int here_int= alpha >> (FIXPT_SHIFT - AADEPTH);
assert(here_int <= AAMAXVAL);
if (!(here_int==0 || here_int==AAMAXVAL)) monochrome=0;
ci->d[p.y * ci->w + p.x]= '0' + here_int;
if (!rd)
rd= ocr_init(text_h);
- progress("Scanning page %d...",page);
+ progress("Processing page %d...",page);
const char *tab= "";
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");
// 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;
}
}
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);
- if (alpha >= 0.49) {
+ Fixpt alpha= find_aa_density(ri,p);
+ if (alpha >= dbl2fixpt(0.49)) {
runs[nruns]++;
pattern |= 1u;
} else {