Skip to content

Commit

Permalink
add ability to detect and print white space
Browse files Browse the repository at this point in the history
This adds an option to enable white spece detection, and two
further options to control the operation of white space detection.

White space detection (--print-spaces) is intended for use cases
where digit (resp. character) grouping is important for correct
interpretation.  One use case is the recognition of superimposed
dates in photographic images.

This commit also increases the version number to 2.21.0 and tweaks
some debug output.
  • Loading branch information
auerswal committed Apr 25, 2021
1 parent 1617787 commit 113d665
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 5 deletions.
7 changes: 6 additions & 1 deletion defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#define SSOCR2_DEFINES_H

/* version number */
#define VERSION "2.20.0"
#define VERSION "2.21.0"

/* states */
#define FIND_DARK 0
Expand Down Expand Up @@ -103,6 +103,9 @@
/* a minus sign is recognized by a width/height ratio > MINUS_RATIO (as ints) */
#define MINUS_RATIO 2

/* add space characters if digit distance is greater than SPC_FAC * min dist */
#define SPC_FAC 1.4

/* to find segment need # of pixels */
#define NEED_PIXELS 1

Expand All @@ -126,6 +129,8 @@
#define ASCII_ART_SEGMENTS (1<<8)
#define PRINT_AS_HEX (1<<9)
#define OMIT_DECIMAL (1<<10)
#define PRINT_SPACES (1<<11)
#define SPC_USE_AVG_DST (1<<12)

/* colors used by ssocr */
#define SSOCR_BLACK 0
Expand Down
9 changes: 7 additions & 2 deletions help.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ void usage(char *name, FILE *f)
fprintf(f, " percentages of used values\n");
fprintf(f, " -l, --luminance=KEYWORD compute luminance using formula KEYWORD\n");
fprintf(f, " use -l help for list of KEYWORDS\n");
fprintf(f, " -s, --print-spaces print spaces between more distant digits\n");
fprintf(f, " -A, --space-factor=FAC relative distance to add spaces\n");
fprintf(f, " -G, --space-average use average instead of minimum distance\n");
fprintf(f, " to determine spaces between digits\n");
fprintf(f, " -S, --ascii-art-segments print recognized segments a ASCII art\n");
fprintf(f, " -X, --print-as-hex change output format to hexadecimal\n");
fprintf(f, " -C, --omit-decimal-point omit decimal points from output\n");
Expand Down Expand Up @@ -169,8 +173,8 @@ void usage(char *name, FILE *f)
fprintf(f, " r_threshold make image monochrome using only red channel\n");
fprintf(f, " g_threshold make image monochrome using only green channel\n");
fprintf(f, " b_threshold make image monochrome using only blue channel\n");
fprintf(f, " white_border [WIDTH] make border of WIDTH (or 1) of image have\n");
fprintf(f, " background color\n");
fprintf(f, " white_border [WIDTH] make border of WIDTH (or 1) in background\n");
fprintf(f, " color\n");
fprintf(f, " shear OFFSET shear image OFFSET pixels (at bottom) to the\n");
fprintf(f, " right\n");
fprintf(f, " rotate THETA rotate image by THETA degrees\n");
Expand All @@ -195,6 +199,7 @@ void usage(char *name, FILE *f)
fprintf(f, " width/height threshold for minus sign = %2d\n", MINUS_RATIO);
fprintf(f, " max_dig_h/h threshold for decimal sep = %2d\n", DEC_H_RATIO);
fprintf(f, " max_dig_w/w threshold for decimal sep = %2d\n", DEC_W_RATIO);
fprintf(f, " space width factor = %.2f\n", SPC_FAC);
fprintf(f, " character set = ");
print_cs_key(DEFAULT_CHARSET, f); fputs("\n", f);
fprintf(f, "\nOperation: The IMAGE is read, the COMMANDs are processed in the sequence\n");
Expand Down
11 changes: 11 additions & 0 deletions ssocr.1.in
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,17 @@ the used formula.
The default of
.I Rec709
should work well in most cases.
.SS -s, --print-spaces
Print space characters between digits (characters) that are farther apart
than a factor times the minimum distance between digits (characters).
.SS -A, --space-factor FACTOR
Use the given
.B FACTOR
instead of the default value to determine white space between digits
(characters).
.SS -G, --space-average
Use the average distance between digits (characters) instead of the minimum
distance to determine white space between digits.
.SS -S, --ascii-art-segments
Prints the recognized segments, i.e. the display as seen by
.BR ssocr ,
Expand Down
108 changes: 107 additions & 1 deletion ssocr.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ static unsigned int scanline(Imlib_Image *image, Imlib_Image *debug_image,
return found_pixels;
}

/* print given number of space characters to given stream */
static void print_spaces(FILE *f, int n)
{
int i;
for (i = 0; i < n; i++) {
fputc(' ', f);
}
}

/*** main() ***/

int main(int argc, char **argv)
Expand All @@ -156,6 +165,7 @@ int main(int argc, char **argv)
int minus_ratio = MINUS_RATIO; /* height/width > minus_ratio => char 'minus'*/
int dec_h_ratio = DEC_H_RATIO; /* max_dig_h/h > dec_h_ratio => possibly '.' */
int dec_w_ratio = DEC_W_RATIO; /* max_dig_w/w > dec_w_ratio => possibly '.' */
double spc_fac = SPC_FAC; /* add spaces if digit distance > spc_fac*min_dst */
double thresh=THRESHOLD; /* border between light and dark */
int offset; /* offset for shear */
double theta; /* rotation angle */
Expand Down Expand Up @@ -217,9 +227,13 @@ int main(int argc, char **argv)
{"charset", 1, 0, 'c'}, /* omit decimal points from output */
{"dec-h-ratio", 1, 0, 'H'}, /* height ratio for decimal point detection */
{"dec-w-ratio", 1, 0, 'W'}, /* width ratio for decimal point detection */
{"print-spaces", 0, 0, 's'}, /* print spaces between distant digits */
{"space-factor", 1, 0, 'A'}, /* relative distance to add spaces */
{"space-average", 0, 0, 'G'}, /* avg instead of min dst for spaces */
{0, 0, 0, 0} /* terminate long options */
};
c = getopt_long (argc, argv, "hVt:vaTn:i:d:r:m:o:O:D::pPf:b:Igl:SXCc:H:W:",
c = getopt_long (argc, argv,
"hVt:vaTn:i:d:r:m:o:O:D::pPf:b:Igl:SXCc:H:W:sA:G",
long_options, &option_index);
if (c == -1) break; /* leaves while (1) loop */
switch (c) {
Expand Down Expand Up @@ -416,6 +430,33 @@ int main(int argc, char **argv)
}
}
break;
case 's':
flags |= PRINT_SPACES;
if(flags & DEBUG_OUTPUT) {
fprintf(stderr, "flags & PRINT_SPACES=%d\n", flags & PRINT_SPACES);
}
break;
case 'A':
if(optarg) {
spc_fac = atof(optarg);
if(spc_fac < 1.0) {
spc_fac = SPC_FAC;
if(flags & (VERBOSE | DEBUG_OUTPUT)) {
fprintf(stderr, "ignoring --space-factor=%s\n", optarg);
}
}
if(flags & DEBUG_OUTPUT) {
fprintf(stderr, "spc_fac = %f (default: %f)\n", spc_fac, SPC_FAC);
}
}
break;
case 'G':
flags |= SPC_USE_AVG_DST;
if(flags & DEBUG_OUTPUT) {
fprintf(stderr, "flags & SPC_USE_AVG_DST=%d\n",
flags & SPC_USE_AVG_DST);
}
break;
case '?': /* missing argument or character not in optstring */
short_usage(PROG,stderr);
exit (2);
Expand All @@ -440,6 +481,15 @@ int main(int argc, char **argv)
fprintf(stderr, "flags & ABSOLUTE_THRESHOLD=%d\n",flags&ABSOLUTE_THRESHOLD);
fprintf(stderr, "flags & DO_ITERATIVE_THRESHOLD=%d\n",
flags & DO_ITERATIVE_THRESHOLD);
fprintf(stderr, "flags & USE_DEBUG_IMAGE=%d\n", flags & USE_DEBUG_IMAGE);
fprintf(stderr, "flags & DEBUG_OUTPUT=%d\n", flags & PRINT_INFO);
fprintf(stderr, "flags & PROCESS_ONLY=%d\n", flags & PROCESS_ONLY);
fprintf(stderr, "flags & ASCII_ART_SEGMENTS=%d\n",
flags & ASCII_ART_SEGMENTS);
fprintf(stderr, "flags & PRINT_AS_HEX=%d\n", flags & PRINT_AS_HEX);
fprintf(stderr, "flags & OMIT_DECIMAL=%d\n", flags & OMIT_DECIMAL);
fprintf(stderr, "flags & PRINT_SPACES=%d\n", flags & PRINT_SPACES);
fprintf(stderr, "flags & SPC_USE_AVG_DST=%d\n", flags & SPC_USE_AVG_DST);
fprintf(stderr, "need_pixels = %d\n", need_pixels);
fprintf(stderr, "ignore_pixels = %d\n", ignore_pixels);
fprintf(stderr, "number_of_digits = %d\n", number_of_digits);
Expand All @@ -455,6 +505,7 @@ int main(int argc, char **argv)
fprintf(stderr, "width/height threshold for minus = %d\n", minus_ratio);
fprintf(stderr, "max_dig_h/h threshold for decimal = %d\n", dec_h_ratio);
fprintf(stderr, "max_dig_w/w threshold for decimal = %d\n", dec_w_ratio);
fprintf(stderr, "distance factor for adding spaces = %.2f\n", spc_fac);
fprintf(stderr, "optind=%d argc=%d\n", optind, argc);
fprintf(stderr, "================================================================================\n");
}
Expand Down Expand Up @@ -1290,6 +1341,56 @@ int main(int argc, char **argv)
}
}

/* check spacing of digits when --print-spaces is given and there are more
* more than two digits
*/
if ((flags & PRINT_SPACES) && (number_of_digits > 2)) {
int min_dst, avg_dst, dst_sum, cur_dst, base_dst, num_spc;
if (flags & DEBUG_OUTPUT) {
fputs("looking for white space\n", stderr);
}

/* determine distance between digits */
min_dst = dst_sum = digits[1].x2 - digits[0].x2;
if (flags & DEBUG_OUTPUT) {
fprintf(stderr, " distance between digits 0 and 1 is %d\n", min_dst);
}
for (i = 2; i < number_of_digits; i++) {
cur_dst = digits[i].x2 - digits[i-1].x2;
if (flags & DEBUG_OUTPUT) {
fprintf(stderr, " distance between digits %d and %d is %d\n",
i-1, i, cur_dst);
}
if (cur_dst < min_dst) {
min_dst = cur_dst;
}
dst_sum += cur_dst;
}
avg_dst = dst_sum / (number_of_digits - 1);
base_dst = (flags & SPC_USE_AVG_DST) ? avg_dst : min_dst;
if (base_dst < 1) {
base_dst = 1;
}
if (flags & DEBUG_OUTPUT) {
fprintf(stderr, " minimum digit distance: %d\n", min_dst);
fprintf(stderr, " average digit distance: %d\n", avg_dst);
fprintf(stderr, " adding spaces for distance greater than: %d\n",
(int) (spc_fac * base_dst));
}

/* determine number of spaces after each digit */
for (i = 0; i < (number_of_digits - 1); i++) {
num_spc = (int) ((digits[i+1].x2 - digits[i].x2) / (spc_fac * base_dst));
if (num_spc > 0) {
if (flags & DEBUG_OUTPUT) {
fprintf(stderr, " adding %d space character(s) after digit %d\n",
num_spc, i);
}
digits[i].spaces = num_spc;
}
}
}

/* print found segments as ASCII art if debug output is enabled
* or ASCII art output is requested explicitely
* example digits known by ssocr:
Expand All @@ -1305,6 +1406,7 @@ int main(int argc, char **argv)
fputc(' ', stderr);
digits[i].digit & HORIZ_UP ? fputc('_', stderr) : fputc(' ', stderr);
fputc(' ', stderr);
print_spaces(stderr, digits[i].spaces * 3);
}
fputc('\n', stderr);
/* middle row */
Expand All @@ -1314,6 +1416,7 @@ int main(int argc, char **argv)
digits[i].digit & HORIZ_MID ? fputc('_', stderr) :
digits[i].digit == D_MINUS ? fputc('_', stderr) : fputc(' ', stderr);
digits[i].digit & VERT_RIGHT_UP ? fputc('|', stderr) : fputc(' ', stderr);
print_spaces(stderr, digits[i].spaces * 3);
}
fputc('\n', stderr);
/* bottom row */
Expand All @@ -1323,6 +1426,7 @@ int main(int argc, char **argv)
digits[i].digit&HORIZ_DOWN ? fputc('_', stderr) :
digits[i].digit == D_DECIMAL ? fputc('.', stderr) : fputc(' ', stderr);
digits[i].digit&VERT_RIGHT_DOWN ? fputc('|', stderr) : fputc(' ', stderr);
print_spaces(stderr, digits[i].spaces * 3);
}
fputs("\n\n", stderr);
}
Expand All @@ -1332,11 +1436,13 @@ int main(int argc, char **argv)
for(i=0; i<number_of_digits; i++) {
if(i > 0) putchar(':');
printf("%02x", digits[i].digit);
print_spaces(stdout, digits[i].spaces);
}
} else {
init_charset(charset);
for(i=0; i<number_of_digits; i++) {
unknown_digit += print_digit(digits[i].digit, flags);
print_spaces(stdout, digits[i].spaces);
}
}
putchar('\n');
Expand Down
2 changes: 1 addition & 1 deletion ssocr.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#define SSOCR2_H

typedef struct {
int x1,y1,x2,y2,digit;
int x1,y1,x2,y2,digit,spaces;
} digit_struct;

typedef struct {
Expand Down

0 comments on commit 113d665

Please sign in to comment.