Browse code

Initial commit

Dario Rodriguez authored on 28/10/2020 22:49:01
Showing 1 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,93 @@
1
+#!/usr/bin/pike
2
+/*
3
+ * jpgscanclean.pike
4
+ *
5
+ *  Utility to clean the background of scanned pages (req. RGB page)
6
+ *
7
+ * Author: Dario Rodriguez dario@softhome.net
8
+ * The program is licensed under the terms of the MIT/X license.
9
+ */
10
+
11
+int bgthreshold=64; // from 0 to 255
12
+int amplitude=15; // from 1 to 255
13
+
14
+int
15
+main(int argc, array(string) argv)
16
+{
17
+	Image.Image in,out,inhsv,indistance;
18
+	string infile,outfile;
19
+        if(argc!=3 || argv[argc-1]=="--help") {
20
+                write("Syntax: "+argv[0]+" infile.jpg outfile.png\n");
21
+                return(1);
22
+        }
23
+	write(argv[1]+" -> "+argv[2]+"\n");
24
+	write("* Generating intermediate representations...");
25
+	infile=argv[1];
26
+	outfile=argv[2];
27
+	in=Image.load(infile);
28
+	inhsv=in->copy()->rgb_to_hsv();
29
+	indistance=in->copy()->distancesq(255,255,255);
30
+	out=Image.Image(in.xsize(),in.ysize());
31
+	// Guess the most used bg color
32
+	write("done.\n* Guessing most used bg hue...");
33
+	array(int) hues=allocate(256);
34
+	int x,y;
35
+	int h,n,selh,seln,j;
36
+	int c;
37
+	for(y=0;y<in.ysize();y++) {
38
+		for(x=0;x<in.xsize();x++) {
39
+			c=indistance.getpixel(x,y)[0];
40
+			if(c<bgthreshold) {
41
+				// possible bg
42
+				c=inhsv.getpixel(x,y)[0];
43
+				hues[c]++;				
44
+			}
45
+		}
46
+		if(!(y%1000))
47
+			write(".");
48
+	}
49
+	for(selh=0,seln=0,h=0;h<256;h++) {
50
+		for(n=0,j=-amplitude;j<amplitude;j++) {
51
+			n+=hues[(h+256+j)%256];
52
+		}
53
+		if(n>seln) {
54
+			seln=n;
55
+			selh=h;
56
+		}
57
+	}
58
+	write(""+selh);
59
+	// Clean image
60
+	write(".\n* Cleaning image...");
61
+	int d;
62
+	for(y=0;y<in.ysize();y++) {
63
+		for(x=0;x<in.xsize();x++) {
64
+			c=indistance.getpixel(x,y)[0];
65
+			h=inhsv.getpixel(x,y)[0];
66
+			// calc. hue distance to bg hue wrapping on the color wheel
67
+			if(h<selh) {
68
+				if((selh-h)<(h+256-selh))
69
+					d=selh-h;
70
+				else
71
+					d=h+256-selh;
72
+			} else {
73
+				if((h-selh)<(selh+256-h))
74
+					d=h-selh;
75
+				else
76
+					d=selh+256-h;
77
+			}
78
+			// heuristics
79
+			if(c<bgthreshold && d<bgthreshold) {
80
+				out.setpixel(x,y,255,255,255);
81
+			} else {
82
+				array(int) rgb=in.getpixel(x,y);
83
+				out.setpixel(x,y,rgb[0],rgb[1],rgb[2]);
84
+			}
85
+		}
86
+		if(!(y%1000))
87
+			write(".");
88
+	}
89
+	// Write result
90
+	write("done.\n* Writing result to disk...");
91
+	Stdio.write_file(outfile,Image.PNG.encode(out));
92
+	write("done.\n* Process finished.\n");
93
+}