76 Commits

Author SHA1 Message Date
Erik Auerswald 443b100ab9 bump version number to 2.25.1 2025-10-31 19:44:16 +01:00
Erik Auerswald 63495ef4a8 suppress debug output without -P, --debug-output
Again, a debug message was not properly guarded with a check
for the debug-flag.
2025-10-30 00:04:42 +01:00
Erik Auerswald 9d9b2253e1 bump version number to 2.25.0 2025-03-23 19:06:24 +01:00
Erik Auerswald e914669079 add option -F, --adapt-after-crop
When this option is used, the threshold is adapted to the cropped
image, i.e., after the "crop" command, but not directly before.
This allows to avoid adjusting the threshold to the full image,
and thus potentially reduce the time needed for recognition.
2025-03-23 19:03:48 +01:00
Erik Auerswald 94ce321060 lazily adapt threshold to image
Instead of adapting the threshold to the image before executing
commands, adapt the threshold just before it is needed.

This allows to avoid theshold adaptation when -p, --process-only
is used with only the "grayscale" and/or "mirror" commands.

This also prepares the code to allow introduction of a new option
to avoid adapting the threshold to the original image before the
"crop" command is applied.
2025-03-23 18:54:13 +01:00
Erik Auerswald 7cae796188 ssocr.c: code maintenance
Fix two minor issues with crop command execution:

 * correct two variable names in a comment, and
 * remove a useless imlib_context_set_image() call.
2025-03-23 14:27:52 +01:00
Erik Auerswald 7f2a9f3f22 warn when options -a and -T are used together 2025-03-22 18:45:15 +01:00
Erik Auerswald 00312ee70e man page: describe interaction of -a and -T
Option -a, --absolute-threshold inhibts the effect of option
-T, --iter-threshold.
2025-03-22 18:38:04 +01:00
Erik Auerswald e309861f24 man page: suggest -a when using gray_stretch 2025-03-20 21:23:33 +01:00
Erik Auerswald 4b5c6ea770 NEWS: mention speed up of -g with gray_stretch
Commit 67abe0fba8 improved the
speed for determining both minimum and maximum luminance (gray)
values for the image.  This speeds up some debugging output,
and also using the gray_stretch command together with option -g.
(I did not notice that initially.)
2025-03-20 21:15:01 +01:00
Erik Auerswald 56d1b22118 simplify some command execution code paths
Commands with optional argument had two code paths leading
to the respective function application, one of those with
hard-coded argument "1".  Instead, ensure the variable for
the optional argument is always set, and have just one
function call, always using this variable, per command.
2025-03-20 21:12:00 +01:00
Erik Auerswald eaf0f32850 NEWS: mention performance improvement 2025-03-18 21:45:00 +01:00
Erik Auerswald fa30f473e7 simplify adapt_threshold() and iterative_threshold()
Both functions are always called with the same arguments.
Only the get_threshold() function is also called with
different x, y, w, h arguments (when used during dynamic
thresholding).
2025-03-18 21:31:19 +01:00
Erik Auerswald 67abe0fba8 combine get_minval() and get_maxval()
This simplifies the code a bit, and slightly speeds up using
option "-P, --debug-output".
2025-03-18 20:42:38 +01:00
Erik Auerswald ac060de96b speed up reading from standard input
Instead of reading one byte at a time, read data in chunks
of BUFSIZ bytes.

For one example, this improves recognition time for image
data read via standard input from 281ms to 53ms.  YMMV.
2025-03-18 20:10:51 +01:00
Erik Auerswald 74aeb44f94 rename draw_pixel() to draw_fg_bg_pixel() 2025-02-02 20:42:52 +01:00
Erik Auerswald f012c14d93 refactoring and type consistency fixes
* The draw_pixel() function was called with an "image" parameter
  of type "Imlib_Image" instead of "Imlib_Image *".  This type
  error did not result in a compilation error, and thus stayed
  undetected in the code.

* Introduce a new function draw_color_pixel() similar to draw_pixel(),
  and use it instead of repeatedly open-coding this operation.
2025-02-02 20:32:48 +01:00
Erik Auerswald b44a4ad72a update copyright years 2025-02-01 19:33:29 +01:00
Erik Auerswald 13a5ec3802 imgproc.c: remove some useless code
The removed code was intended to clear the image to allow
only drawing foreground pixels in the following loop.  But
it only drew the outline of a rectangle and thus did not
clear the image as intended.

Since the image is not cleared, the following loop already
draws every pixel, overwriting any previously drawn rectangle
anyway.
2025-02-01 19:26:09 +01:00
Erik Auerswald 2824d0aea7 ensure M_PI is defined
Some image manipulation functions use trigonometric functions.
This includes using the number Pi.  Pi is often available as
M_PI via including <math.h>.  This constant is part of the Unix98
standard, not the C standard itself.  According to the GCC
documentation[1], M_PI is only defined when the feature selection
macro _XOPEN_SOURCE=500 is used.  This seems to be default in
many versions of GNU/Linux, since ssocr could always use M_PI
without explicitly setting _XOPEN_SOURCE=500.

An MPlayer bug report[2] reported a build failure because M_PI
was not defined.  This lead to a patch[3] to work around this
problem.

I want to avoid running into this specific problem in the future,
without introducing significant changes to ssocr.  Thus I check
if M_PI is defined after inlcuding <math.h>, and define it myself
if it is missing.  I use the value found in /usr/include/math.h
from GNU Libc on my current system (Ubuntu GNU/Linux 20.04.6 LTS).

[1] https://www.gnu.org/software/libc/manual/html_node/Mathematical-Constants.html
[2] https://trac.mplayerhq.hu/ticket/2423
[3] https://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2024-December/074244.html

Also add '+' to the version number to indicate changes after the
latest release.
2024-12-14 14:56:13 +01:00
Erik Auerswald 5439679c83 bump version number to 2.24.1 2024-12-11 15:43:49 +01:00
Erik Auerswald e7a20fbb2d man page: fix two typos 2024-12-11 15:38:10 +01:00
Erik Auerswald 88a627050a print warning when ignoring unknown luminance formula 2024-11-18 17:55:02 +01:00
Erik Auerswald 6e8c8361fd improve wording of unknown charset warning 2024-11-18 17:43:55 +01:00
Erik Auerswald ad5b6da118 NEWS: mention recent changes 2024-11-17 19:44:57 +01:00
Erik Auerswald 7485ba3ffc man page: option argument separation description 2024-11-17 19:33:35 +01:00
Erik Auerswald acdf26c6bf print warning when ignoring unknown charset 2024-11-17 19:25:33 +01:00
Erik Auerswald 4ab3869eea add '+' to version to indicate unreleased changes 2024-11-17 19:13:33 +01:00
Erik Auerswald 70692aa5c4 suppress debug output without -P, --debug-output 2024-11-17 19:10:34 +01:00
Erik Auerswald 9964c8ce85 fix copy & paste error in a comment 2024-11-17 19:09:00 +01:00
Erik Auerswald 895b0cb2b5 bump version number to 2.24.0 2024-06-22 20:05:30 +02:00
Erik Auerswald 894f3035fd fix a special case for decimal point recognition
When the widest digit found in the image is a one, it is likely
that a decimal separator is nearly as wide as this digit.  Thus
it cannot be recognized, because the decimal separator needs to
be at most half as wide as the widest digit (before this commit).

Thus add an additional pass over the digits for this special case.
This pass comes after the existing recognition passes for the
digit one, decimal separator, and minus sign.  In the new pass,
the width of the digit is ignored.

This addresses GitHub issue #26.
2024-06-22 20:04:08 +02:00
Erik Auerswald 40c34ad6d7 tweak --help and --version output 2024-05-19 01:05:22 +02:00
Erik Auerswald bae7381e34 add lower case r to character set "full" 2024-05-18 23:51:13 +02:00
Erik Auerswald d6be469e14 add lower case h to character set "full" 2024-05-18 23:49:07 +02:00
Erik Auerswald af6c53c3f3 add lower case n for consistency with lower case c
Neither lower case c nor lower case n can happen with correct
image segmentation.  Lower case c was already used in the code,
but lower case n was only found as a comment.

I am not sure if I want to keep this or rather remove both lower
case variants.  I do want to have this consistent, though.
2024-05-18 21:44:42 +02:00
Erik Auerswald b05410efae man page: fix "white_border" description
The command name stems from the time when ssocr always considered
"white" as background and "black" as foreground.  The intention
has always been to ensure some background border around the seven
segment displays, and the implementation always followed this.  The
output of --help correctly uses "background" for the "white_border"
description.  Now, the man page description is correct, too.
2024-05-09 16:19:36 +02:00
Erik Auerswald 6569ca9f6b update copyright years 2024-02-23 19:03:58 +01:00
Erik Auerswald 48da4ee8c1 help: align equal signs in Defaults section 2024-02-23 18:58:58 +01:00
Erik Auerswald 1a8c4d7701 help: mention that rotate is clockwise 2024-02-23 18:57:04 +01:00
Erik Auerswald 624e998efb NEWS: mention message improvements 2023-09-10 14:54:27 +02:00
Erik Auerswald 81c5472b69 add program name to warning messages 2023-09-10 14:49:12 +02:00
Erik Auerswald 6fc62729e9 improve error message for wrong number of digits
* Use different messages for single digit and digit ranges.
* Use singular when looking for one digit, plural otherwise.
2023-09-10 14:35:49 +02:00
Erik Auerswald 19f93dcb58 fix debug output regarding flag DEBUG_OUTPUT 2023-07-26 19:50:15 +02:00
Erik Auerswald 5ca3455873 add ssocr version to debug output 2023-07-26 19:47:01 +02:00
Erik Auerswald 2026f39ee7 INSTALL: tweak prerequisites list 2023-05-21 18:45:08 +02:00
Erik Auerswald 73e7a69b4c INSTALL: mention (GNU) make as prerequisite 2023-05-20 19:37:29 +02:00
Erik Auerswald f25047745d INSTALL: mention gcc and man under prerequisites 2023-05-20 16:58:38 +02:00
Erik Auerswald 658230679a bump version number to 2.23.1 2023-05-18 16:13:18 +02:00
Erik Auerswald 1fe392c772 use latest release date as man page date
The latest release date is extracted from the NEWS file,
i.e., it depends only on the sources, not the build date.
This is intended to help in creating reproducible builds
by avoiding timestamps.  It is also closer to the date of
the contents of the man page than using just the latest
copyright year.

I do not have a perfect solution that works for both a git
clone and a downloaded tar ball.  This solution works well
for released tar balls of the ssocr sources.
2023-05-14 17:37:48 +02:00
Erik Auerswald 2ff3d882b9 Makefile: remove quotes from inside VERSION variable 2023-05-14 17:21:37 +02:00
Erik Auerswald f06f8441fd Makefile: use single quote when possible 2023-05-14 17:01:26 +02:00
Erik Auerswald a5c550b72b Makefile: man page also depends on help.c 2023-05-14 16:26:34 +02:00
Erik Auerswald 0c3adc9002 avoid useless digit memory copy
There is no need to copy digit memory if all potential
digits are kept.
2023-05-13 20:05:23 +02:00
Erik Auerswald ad9027b6a0 guard against some integer overflows
When determining memory allocation sizes, integer overflow can
lead to memory safety errors.  Add some guards to prevent this.
2023-05-13 19:58:16 +02:00
Erik Auerswald 66dbee3591 typo fix in NEWS 2023-05-12 18:28:16 +02:00
Erik Auerswald c6e09b8f70 INSTALL, README: add commas around "e.g." 2023-05-12 18:27:19 +02:00
Erik Auerswald 7e056835fa man page: mention -- to end option-scanning 2023-05-11 21:25:31 +02:00
Erik Auerswald 050830a709 man page: use latest copyright year, not build date
In order to help creating reproducible builds of ssocr,
do not use the build day of the man page as the date
inside the man page.  Instead, use the latest copyright
year of ssocr.

Using the man page build date has always been problematic,
because it is misleading.  But I do not have a general
automatic way to maintain the last change date for the
man page that works for both git clones and tar balls.
This seems like an improvement to me.  It provides some
idea of how old the man page is, and this date depends
only on the ssocr source code, not the build date.

This should help with one of the two problems reported
in GitHub issue #22.
2023-05-09 18:11:53 +02:00
Erik Auerswald 27e7913135 append '+' to version to indicate changes 2023-05-09 18:10:25 +02:00
Erik Auerswald 0cd776b479 bump version number to 2.23.0
This ssocr release adds new features and thus addresses
GitHub issue #21:

* new option -N, --min-segment=SIZE
* new option -M, --min-char-dims=WxH
* a range of expected digits can be specified (before, only
  a single number could be specified, or the number could be
  left unspecified)
2023-05-01 19:36:47 +02:00
Erik Auerswald cf2391f400 do not accept 0 expected digits
This did not work before, and it was not intended to change
this.

I do not know of a use case where one is expecting no digits
at all, but is using ssocr to recognize the non-existing
digits.  If you do have such a use case, let me know.
2023-05-01 17:00:49 +02:00
Erik Auerswald 898f5ec712 allow to specify a range for the number of digits
This can be helpful when using ssocr with a display showing
a variable number of digits, e.g., a clock, a scale, or a
thermometer.
2023-05-01 16:19:12 +02:00
Erik Auerswald 9e2d37ddbf add option -M, --min-char-dims=WxH
When there is a bit of noise in the image, the segmentation
step might find lots of small potential digits that are not
really digits (or other characters) of the display.  Given
sufficiently large display characters, it may be possible
to specify minimum character dimensions to remove spurious
potential characters (digits) based on their size.
2023-04-30 19:14:19 +02:00
Erik Auerswald 8df40937c9 accept any number of digits during segmentation
If a specific number of digits is expected, i.e., without
-d-1, the number of found (potential) digits is compared
with the expected number, and ssocr errors out on mismatch.

This prepares for the introduction of an option to reject
some potential images, e.g., because they are too small to
contain a digit or character from the display.

It also prepares for allowing a range of digits as the
expected segmentation result, e.g., for a clock display
with a blinking colon (:), or for a thermometer display.
2023-04-30 16:29:47 +02:00
Erik Auerswald 06c2afc85e add option -N, --min-segment=SIZE
This option is similar to -n, --number-pixels=#, but also
applies the limit to ratio based detection (i.e., for
recognition of "one" and "minus").
2023-04-29 11:53:32 +02:00
Erik Auerswald 2d6b019842 consistently use "scanline" in comments 2023-04-24 17:04:34 +02:00
Erik Auerswald 8660a65ebd append '+' to version string during development 2023-04-24 17:03:33 +02:00
Erik Auerswald fe272d21ef bump version number to 2.22.2
This "bug fix" release comprises documentation improvements only.
2023-04-23 14:45:57 +02:00
Erik Auerswald 61721919cc man page: --ignore-pixels pertains to rows, too 2023-04-23 14:39:24 +02:00
Erik Auerswald d5b6c0852d man page: improve descriptions of -r, -m, -H, -W 2023-04-23 13:44:56 +02:00
Erik Auerswald ea8f724846 update copyright years 2023-04-23 12:53:48 +02:00
Erik Auerswald 320487e300 tweak alignment of some debug output 2023-04-23 12:50:02 +02:00
Erik Auerswald 9386643c60 improve help output
The height/width threshold used for recognizing a 1 did
mention this use.
2023-04-23 12:48:37 +02:00
Erik Auerswald f7098c6ff5 man page: add some information
* a general description of options and commands
* so far only the "crop" command changes image dimensions
2022-12-10 13:38:31 +01:00
Erik Auerswald 3ebd31d09d man page: tweak -s, --print-spaces description 2022-12-10 13:19:47 +01:00
15 changed files with 803 additions and 305 deletions
+8 -4
View File
@@ -23,9 +23,10 @@ build a .deb package by typing:
Prerequisites
-------------
- A C compiler compatible with GCC.
- A system sufficiently compatible to POSIX and GNU.
- POSIX utilities: chmod, printf, sh, sed (or compatible)
- GNU utilities: date, gzip, install, tar (or compatible)
- POSIX utilities: chmod, head, printf, sh, sed (or compatible)
- GNU utilities: date, gzip, install, make, tar (or compatible)
- Other utilities: bzip2
- Imlib2 shared library and development headers. On a Debian or Ubuntu system
they are provided by the packages libimlib2 and libimlib2-dev.
@@ -37,8 +38,11 @@ Prerequisites
- Imlib2 requires the X11/Xlib.h header and links against some X11 libraries,
at least on GNU/Linux with X11 GUI, thus X11 shared libraries and development
headers are required for ssocr, too, although ssocr does not use X11 itself
- Build tools, e.g. build-essential on a Debian (or Ubuntu) system.
- Build tools, e.g., build-essential on a Debian (or Ubuntu) system, usually
contain both make and a C compiler.
- To build a .deb package, you probably need the debhelper package.
- To create an HTML version of the man page, you need a man utility that can
produce HTML output.
Additional Makefile Targets
---------------------------
@@ -93,6 +97,6 @@ https://www.unix-ag.uni-kl.de/~auerswal/ssocr/
Third Party Packages
--------------------
There exist third party packaging efforts for e.g. GNU/Linux distributions
There exist third party packaging efforts for, e.g., GNU/Linux distributions
and FreeBSD. Thus you can search the packaging system of your distribution
for an ssocr package.
+5 -4
View File
@@ -8,8 +8,9 @@ BINDIR := $(PREFIX)/bin
MANDIR := $(PREFIX)/share/man/man1
DOCDIR := $(PREFIX)/share/doc/ssocr
DOCS := AUTHORS COPYING INSTALL README THANKS NEWS
VERSION := $(shell sed -n 's/^.*VERSION.*\(".*"\).*/\1/p' defines.h)
VERSION := $(shell sed -n 's/^.*VERSION.*"\(.*\)".*/\1/p' defines.h)
CRYEARS := $(shell sed -n 's/^.*fprintf.*Copyright.*\(2004-2[0-9][0-9][0-9]\).*Erik.*Auerswald.*$$/\1/p' help.c)
RELDATE := $(shell sed -n 's/^Version [.0-9]* .\([-0-9]*\).*$$/\1/p' NEWS | head -n1)
all: ssocr ssocr.1
@@ -20,9 +21,9 @@ imgproc.o: imgproc.c defines.h imgproc.h help.h Makefile
help.o: help.c defines.h imgproc.h help.h Makefile
charset.o: charset.c charset.h defines.h help.h Makefile
ssocr.1: ssocr.1.in Makefile defines.h
ssocr.1: ssocr.1.in Makefile defines.h help.c NEWS
sed -e 's/@VERSION@/$(VERSION)/' \
-e "s/@DATE@/$(shell date +%Y-%m-%d)/" \
-e 's/@DATE@/$(RELDATE)/' \
-e 's/@CRYEARS@/$(CRYEARS)/' <$< >$@
ssocr-manpage.html: ssocr.1
@@ -43,7 +44,7 @@ ssocr-dir:
chmod +x ssocr-$(VERSION)/notdebian/rules
notdebian/changelog:
printf "ssocr ($(VERSION)-1) unstable; urgency=low\n\n * self built package of current ssocr version in .deb format\n\n -- $(USER) $(shell date -R)\n" >$@
printf 'ssocr ($(VERSION)-1) unstable; urgency=low\n\n * self built package of current ssocr version in .deb format\n\n -- $(USER) $(shell date -R)\n' >$@
selfdeb: notdebian/changelog notdebian/control notdebian/rules ssocr-dir
(cd ssocr-$(VERSION); ln -sv notdebian debian; fakeroot debian/rules binary; fakeroot debian/rules clean; rm -f debian)
+48
View File
@@ -1,6 +1,54 @@
Noteworthy Changes in ssocr Releases
====================================
Version 2.25.1 (2025-10-31):
----------------------------
* Fix one debug message to be printed only with -P, --debug-output
Version 2.25.0 (2025-03-23):
----------------------------
* New option -F, --adapt-after-crop to skip threshold adjustment directly
before cropping the image
* Print warning when the two options -a, --absolute-threshold and -T,
--iter-threshold are used together because -a inhibits -T
* Improved performance when reading image data via standard input
* Improved performance when using gray_stretch together with -g
* Improved performance when using option -p, --process-only together
with only the grayscale and/or mirror commands
* Documentation improvements
Version 2.24.1 (2024-12-11):
----------------------------
* Print warning when an unknown charset name is ignored
* Print warning when an unknown luminance formula name is ignored
* Fix one debug message to be printed only with -P, --debug-output
* Documentation improvements
Version 2.24.0 (2024-06-22):
----------------------------
* Fix decimal separator recognition when widest digit is a one
* Add recognition of lower case variant of character 'h' to full charset
* Add recognition of lower case variant of character 'r' to full charset
* Documentation improvements
* Error, warning, and debug message improvements
Version 2.23.1 (2023-05-18):
----------------------------
* The man page uses the latest ssocr release date as its date (to help
in creating reproducible builds)
* Documentation improvements
Version 2.23.0 (2023-05-01):
----------------------------
* New option -N, --min-segment to specify the minimum width and height of
a segment, for both scanline based and ratio based character recognition
* New option -M, --min-char-dims to specify minimum character dimensions
* The option -d, --number-digits now also accepts a range description
Version 2.22.2 (2023-04-24):
----------------------------
* Documentation improvements
Version 2.22.1 (2022-01-25):
----------------------------
* Fix build failure with Imlib 1.7.5 (pkg-config replaces imlib2-config)
+2 -2
View File
@@ -7,7 +7,7 @@ as well), Mac OS X (Homebrew can be used to install the library Imlib2,
used by ssocr), and even on Windows (using Cygwin). ssocr should work
on any UNIX-like or POSIX compatible operating system.
Unless ssocr is installed via some packaging system, e.g. from a GNU/Linux
Unless ssocr is installed via some packaging system, e.g., from a GNU/Linux
distribution, it is distributed in source form and needs to be built
before it can be used. See the INSTALL file for instructions on how to
build ssocr.
@@ -19,7 +19,7 @@ quotes).
You can get the current ssocr version from the official ssocr website:
https://www.unix-ag.uni-kl.de/~auerswal/ssocr/
(Links to ssocr should point to the official website, not to a convenience
copy of the development repository, e.g. on GitHub.)
copy of the development repository, e.g., on GitHub.)
I am usually quicker to reply to emails than to GitHub issues. But
increasingly Google blocks emails sent by me, so if you do not receive
+6 -2
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2018-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2018-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* standard things */
#include <stdio.h> /* puts, printf, BUFSIZ, perror, FILE */
@@ -44,7 +44,7 @@ charset_t parse_charset(char *keyword)
} else if(strncasecmp(keyword, "tt_robot", 8) == 0) {
return CS_TT_ROBOT;
} else {
return DEFAULT_CHARSET;
return CS_PARSE_ERROR;
}
}
@@ -86,9 +86,13 @@ void init_charset(charset_t cs)
charset_array[D_T] = 't';
charset_array[D_L] = 'l';
charset_array[D_H] = 'h';
charset_array[D_h] = 'h';
charset_array[D_R] = 'r';
charset_array[D_ALT_R] = 'r';
charset_array[D_r] = 'r';
charset_array[D_P] = 'p';
charset_array[D_N] = 'n';
charset_array[D_n] = 'n';
charset_array[D_Y] = 'y';
charset_array[D_J] = 'j';
break;
+1 -1
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2018-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2018-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
#ifndef SSOCR2_CHARSET_H
#define SSOCR2_CHARSET_H
+32 -7
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2004-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2004-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2013 Cristiano Fontana <fontanacl@ornl.gov> */
#define PROG "ssocr"
@@ -23,7 +23,7 @@
#define SSOCR2_DEFINES_H
/* version number */
#define VERSION "2.22.1"
#define VERSION "2.25.1"
/* states */
#define FIND_DARK 0
@@ -76,6 +76,7 @@
#define D_HEX_A (ALL_SEGS & ~HORIZ_DOWN)
#define D_HEX_b (ALL_SEGS & ~(HORIZ_UP | VERT_RIGHT_UP))
#define D_HEX_C (ALL_SEGS & ~(VERT_RIGHT_UP | HORIZ_MID | VERT_RIGHT_DOWN))
/* a C in the lower half can only happen when digit boundary detection fails */
#define D_HEX_c (HORIZ_MID | VERT_LEFT_DOWN | HORIZ_DOWN)
#define D_HEX_d (ALL_SEGS & ~(HORIZ_UP | VERT_LEFT_UP))
#define D_HEX_E (ALL_SEGS & ~(VERT_RIGHT_UP | VERT_RIGHT_DOWN))
@@ -84,10 +85,15 @@
#define D_T (ALL_SEGS & ~(HORIZ_UP | VERT_RIGHT_UP | VERT_RIGHT_DOWN))
#define D_L (D_T & ~HORIZ_MID)
#define D_H (ALL_SEGS & ~(HORIZ_UP | HORIZ_DOWN))
#define D_h (VERT_LEFT_UP | VERT_LEFT_DOWN | HORIZ_MID | VERT_RIGHT_DOWN)
#define D_R (D_ZERO & ~(VERT_RIGHT_DOWN | HORIZ_DOWN))
#define D_ALT_R (VERT_LEFT_UP | VERT_LEFT_DOWN | HORIZ_UP)
/* an r in the lower half can only happen when digit boundary detection fails */
#define D_r (VERT_LEFT_DOWN | HORIZ_MID)
#define D_P (D_HEX_F | VERT_RIGHT_UP)
#define D_N (D_ZERO & ~HORIZ_DOWN)
/* an N in the lower half can only happen when digit boundary detection fails *//* define D_LOW_N (VERT_LEFT_DOWN | VERT_RIGHT_DOWN | HORIZ_MID) */
/* an N in the lower half can only happen when digit boundary detection fails */
#define D_n (VERT_LEFT_DOWN | VERT_RIGHT_DOWN | HORIZ_MID)
#define D_Y (ALL_SEGS & ~(HORIZ_UP | VERT_LEFT_DOWN))
#define D_J (HORIZ_DOWN | VERT_RIGHT_UP | VERT_RIGHT_DOWN)
/* add two "wrong" 7 definitions used in a character set for a Chinese
@@ -113,9 +119,21 @@
/* add space characters if digit distance is greater than SPC_FAC * min dist */
#define SPC_FAC 1.4
/* to find segment need # of pixels */
/* number of set pixels needed in a scanline to recognize a segment */
#define NEED_PIXELS 1
/* minimum number of pixels required for a segment
* this generalizes to both scanline and ratio based digit detection,
* but only when the digit is built using segments, i.e., this is not
* used for decimal separators */
#define MIN_SEGMENT 1
/* minimum width of a character respectively digit */
#define MIN_CHAR_W 1
/* minimum height of a character respectively digit */
#define MIN_CHAR_H 1
/* ignore # of pixels when checking a column fo black or white */
#define IGNORE_PIXELS 0
@@ -138,6 +156,7 @@
#define OMIT_DECIMAL (1<<10)
#define PRINT_SPACES (1<<11)
#define SPC_USE_AVG_DST (1<<12)
#define ADAPT_AFTER_CROP (1<<13)
/* colors used by ssocr */
#define SSOCR_BLACK 0
@@ -154,6 +173,10 @@
/* default luminance formula */
#define DEFAULT_LUM_FORMULA REC709
/* when to adapt threshold values to the image */
#define INITIAL 0 /* adapt threshold unless is was already adapted */
#define UPDATE 1 /* adapt threshold even if it was adapted before */
/* foreground and background */
typedef enum fg_bg_e {
FG,
@@ -169,10 +192,11 @@ typedef enum luminance_e {
MAXIMUM,
RED,
GREEN,
BLUE
BLUE,
LUM_PARSE_ERROR
} luminance_t;
/* direction, to mirror horizontally or vertically, or for a scan line */
/* direction, to mirror horizontally or vertically, or for a scanline */
typedef enum direction_e {
HORIZONTAL,
VERTICAL
@@ -184,7 +208,8 @@ typedef enum charset_e {
CS_DIGITS,
CS_DECIMAL,
CS_HEXADECIMAL,
CS_TT_ROBOT
CS_TT_ROBOT,
CS_PARSE_ERROR
} charset_t;
#define DEFAULT_CHARSET CS_FULL
+25 -16
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2004-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2004-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2013 Cristiano Fontana <fontanacl@ornl.gov> */
/* standard things */
@@ -92,11 +92,11 @@ void print_version(FILE *f)
{
fprintf(f, "Seven Segment Optical Character Recognition Version %s\n",
VERSION);
fprintf(f, "Copyright (C) 2004-2022 by Erik Auerswald"
fprintf(f, "Copyright (C) 2004-2025 Erik Auerswald"
" <auerswal@unix-ag.uni-kl.de>\n");
fprintf(f, "This program comes with ABSOLUTELY NO WARRANTY\n");
fprintf(f, "This program comes with ABSOLUTELY NO WARRANTY.\n");
fprintf(f, "This is free software, and you are welcome to redistribute it"
" under the terms\nof the GNU GPL (version 3 or later)\n");
" under the terms\nof the GNU GPL (version 3 or later).\n");
}
/* print short usage */
@@ -120,9 +120,12 @@ void usage(char *name, FILE *f)
fprintf(f, " -a, --absolute-threshold don't adjust threshold to image\n");
fprintf(f, " -T, --iter-threshold use iterative thresholding method\n");
fprintf(f, " -n, --number-pixels=# number of pixels needed to recognize a segment\n");
fprintf(f, " -N, --min-segment=SIZE minimum width and height of a segment\n");
fprintf(f, " -i, --ignore-pixels=# number of pixels ignored when searching digit\n");
fprintf(f, " boundaries\n");
fprintf(f, " -d, --number-digits=# number of digits in image (-1 for auto)\n");
fprintf(f, " -M, --min-char-dims=WxH minimum width and height of a character/digit\n");
fprintf(f, " -d, --number-digits=RNG number of digits in image (-1 for auto,\n");
fprintf(f, " positive number, or positive range)\n");
fprintf(f, " -r, --one-ratio=# height/width ratio to recognize a \'one\'\n");
fprintf(f, " -m, --minus-ratio=# width/height ratio to recognize a minus sign\n");
fprintf(f, " -H, --dec-h-ratio=# max_dig_h/h ratio to recognize decimal point\n");
@@ -148,6 +151,8 @@ void usage(char *name, FILE *f)
fprintf(f, " -C, --omit-decimal-point omit decimal points from output\n");
fprintf(f, " -c, --charset=KEYWORD select recognized characters\n");
fprintf(f, " use -c help for list of KEYWORDS\n");
fprintf(f, " -F, --adapt-after-crop do not adapt threshold to image directly\n"
" before, only after, cropping\n");
fprintf(f, "\nCommands: dilation [N] [N times] dilation algorithm"
"\n (set_pixels_filter with mask"
" of 1 pixel)\n");
@@ -176,7 +181,7 @@ void usage(char *name, FILE *f)
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");
fprintf(f, " rotate THETA rotate image clockwise by THETA degrees\n");
fprintf(f, " mirror {horiz|vert} mirror image horizontally or vertically\n");
fprintf(f, " crop X Y W H crop image with upper left corner (X,Y) with\n");
fprintf(f, " width W and height H\n");
@@ -184,22 +189,26 @@ void usage(char *name, FILE *f)
fprintf(f, " pixels set (including checked position)\n");
fprintf(f, " keep_pixels_filter MASK keeps pixels that have at least MASK neighbor\n");
fprintf(f, " pixels set (not counting the checked pixel)\n");
fprintf(f, "\nDefaults: needed pixels = %2d\n", NEED_PIXELS);
fprintf(f, " ignored pixels = %2d\n", IGNORE_PIXELS);
fprintf(f, " no. of digits = %2d\n", NUMBER_OF_DIGITS);
fprintf(f, " threshold = %5.2f\n", THRESHOLD);
fprintf(f, " foreground = %s\n",
fprintf(f, "\nDefaults: needed pixels = %2d\n", NEED_PIXELS);
fprintf(f, " minimum segment size = %2d\n", MIN_SEGMENT);
fprintf(f, " minimum character width = %2d\n", MIN_CHAR_W);
fprintf(f, " minimum character height = %2d\n", MIN_CHAR_H);
fprintf(f, " ignored pixels = %2d\n", IGNORE_PIXELS);
fprintf(f, " minimum number of digits = %2d\n", NUMBER_OF_DIGITS);
fprintf(f, " maximum number of digits = %2d\n", NUMBER_OF_DIGITS);
fprintf(f, " threshold = %5.2f\n", THRESHOLD);
fprintf(f, " foreground = %s\n",
(SSOCR_DEFAULT_FOREGROUND == SSOCR_BLACK) ? "black" : "white");
fprintf(f, " background = %s\n",
fprintf(f, " background = %s\n",
(SSOCR_DEFAULT_BACKGROUND == SSOCR_BLACK) ? "black" : "white");
fprintf(f, " luminance = ");
fprintf(f, " luminance = ");
print_lum_key(DEFAULT_LUM_FORMULA, f); fprintf(f, "\n");
fprintf(f, " height/width threshold = %2d\n", ONE_RATIO);
fprintf(f, " height/width threshold for digit one = %2d\n", ONE_RATIO);
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 = ");
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");
fprintf(f, " they are given, in the resulting image the given number of digits\n");
+1 -1
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2004-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2004-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
#ifndef SSOCR2_HELP_H
#define SSOCR2_HELP_H
+65 -128
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2004-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2004-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* ImLib2 Header */
#include <X11/Xlib.h> /* needed by Imlib2.h */
@@ -27,8 +27,11 @@
/* string manipulation */
#include <string.h> /* strcasecmp, strcmp, strrchr */
/* sin, cos */
#include <math.h>
/* trigonometry */
#include <math.h> /* sin, cos, M_PI */
#ifndef M_PI /* sometimes, M_PI is not defined */
#define M_PI 3.14159265358979323846
#endif
/* my headers */
#include "defines.h" /* defines */
@@ -76,12 +79,12 @@ void ssocr_set_color(fg_bg_t color)
}
/* draw a fore- or background pixel */
void draw_pixel(Imlib_Image *image, int x, int y, fg_bg_t color)
void draw_fg_bg_pixel(Imlib_Image *image, int x, int y, fg_bg_t color)
{
Imlib_Image *current_image; /* save current image */
current_image = imlib_context_get_image();
imlib_context_set_image(image);
imlib_context_set_image(*image);
ssocr_set_color(color);
imlib_image_draw_pixel(x,y,0);
imlib_context_set_image(current_image);
@@ -90,13 +93,25 @@ void draw_pixel(Imlib_Image *image, int x, int y, fg_bg_t color)
/* draw a foreground pixel */
void draw_fg_pixel(Imlib_Image *image, int x, int y)
{
draw_pixel(image, x, y, FG);
draw_fg_bg_pixel(image, x, y, FG);
}
/* draw a background pixel */
void draw_bg_pixel(Imlib_Image *image, int x, int y)
{
draw_pixel(image, x, y, BG);
draw_fg_bg_pixel(image, x, y, BG);
}
/* draw a pixel of a given color */
void draw_color_pixel(Imlib_Image *image, int x, int y, Imlib_Color color)
{
Imlib_Image *current_image; /* save current image */
current_image = imlib_context_get_image();
imlib_context_set_image(*image);
imlib_context_set_color(color.red, color.green, color.blue, color.alpha);
imlib_image_draw_pixel(x, y, 0);
imlib_context_set_image(current_image);
}
/* check if a pixel is set regarding current foreground/background colors */
@@ -165,9 +180,9 @@ Imlib_Image set_pixels_filter(Imlib_Image *source_image, double thresh,
}
/* set pixel if at least mask pixels around it are set */
if(set_pixel >= mask) {
draw_fg_pixel(new_image, x, y);
draw_fg_pixel(&new_image, x, y);
} else {
draw_bg_pixel(new_image, x, y);
draw_bg_pixel(&new_image, x, y);
}
}
}
@@ -257,12 +272,6 @@ Imlib_Image keep_pixels_filter(Imlib_Image *source_image, double thresh,
width = imlib_image_get_width();
new_image = imlib_clone_image();
/* draw white (background) rectangle to clear new image */
imlib_context_set_image(new_image);
ssocr_set_color(BG);
imlib_image_draw_rectangle(0, 0, width, height);
imlib_context_set_image(*source_image);
/* check for every pixel if it should be set in filtered image */
for(x=0; x<width; x++) {
for(y=0; y<height; y++) {
@@ -285,9 +294,9 @@ Imlib_Image keep_pixels_filter(Imlib_Image *source_image, double thresh,
/* set pixel if at least mask pixels around it are set */
/* mask = 1 keeps all pixels */
if(set_pixel > mask) {
draw_fg_pixel(new_image, x, y);
draw_fg_pixel(&new_image, x, y);
} else {
draw_bg_pixel(new_image, x, y);
draw_bg_pixel(&new_image, x, y);
}
}
}
@@ -402,9 +411,9 @@ Imlib_Image dynamic_threshold(Imlib_Image *source_image,double t,luminance_t lt,
lum = get_lum(&color, lt);
thresh = get_threshold(source_image, t/100.0, lt, x-ww/2, y-ww/2, ww, wh);
if(is_pixel_set(lum, thresh)) {
draw_fg_pixel(new_image, x, y);
draw_fg_pixel(&new_image, x, y);
} else {
draw_bg_pixel(new_image, x, y);
draw_bg_pixel(&new_image, x, y);
}
}
}
@@ -441,9 +450,9 @@ Imlib_Image make_mono(Imlib_Image *source_image, double thresh, luminance_t lt)
imlib_image_query_pixel(x, y, &color);
lum = get_lum(&color, lt);
if(is_pixel_set(lum, thresh)) {
draw_fg_pixel(new_image, x, y);
draw_fg_pixel(&new_image, x, y);
} else {
draw_bg_pixel(new_image, x, y);
draw_bg_pixel(&new_image, x, y);
}
}
}
@@ -456,23 +465,28 @@ Imlib_Image make_mono(Imlib_Image *source_image, double thresh, luminance_t lt)
}
/* adapt threshold to image values values */
double adapt_threshold(Imlib_Image *image, double thresh, luminance_t lt, int x,
int y, int w, int h, unsigned int flags)
double adapt_threshold(Imlib_Image *image, double thresh, luminance_t lt,
unsigned int flags, int force_update)
{
double t = thresh;
if(!(flags & ABSOLUTE_THRESHOLD)) {
static int is_adapted = 0;
if(is_adapted && !force_update) {
if(flags & DEBUG_OUTPUT)
fprintf(stderr, "threshold is already adjusted to image\n");
} else if(!(flags & ABSOLUTE_THRESHOLD)) {
if(flags & DEBUG_OUTPUT)
fprintf(stderr, "adjusting threshold to image: %f ->", t);
t = get_threshold(image, thresh/100.0, lt, x, y, w, h);
t = get_threshold(image, thresh/100.0, lt, 0, 0, -1, -1);
if(flags & DEBUG_OUTPUT)
fprintf(stderr, " %f\n", t);
if(flags & DO_ITERATIVE_THRESHOLD) {
if(flags & DEBUG_OUTPUT)
fprintf(stderr, "doing iterative_thresholding: %f ->", t);
t = iterative_threshold(image, t, lt, x, y, w, h);
t = iterative_threshold(image, t, lt);
if(flags & DEBUG_OUTPUT)
fprintf(stderr, " %f\n", t);
}
is_adapted = 1;
}
if((flags & VERBOSE) || (flags & DEBUG_OUTPUT)) {
fprintf(stderr, "using threshold %.2f\n", t);
@@ -528,7 +542,7 @@ double get_threshold(Imlib_Image *source_image, double fraction, luminance_t lt,
/* determine threshold by an iterative method */
double iterative_threshold(Imlib_Image *source_image, double thresh,
luminance_t lt, int x, int y, int w, int h)
luminance_t lt)
{
Imlib_Image current_image; /* save image pointer */
int height, width; /* image dimensions */
@@ -553,23 +567,13 @@ double iterative_threshold(Imlib_Image *source_image, double thresh,
height = imlib_image_get_height();
width = imlib_image_get_width();
/* special value -1 for width or height means image width/height */
if(w == -1) w = width;
if(h == -1) h = width;
/* assure valid coordinates */
if(x+w > width) x = width-w;
if(y+h > height) y = height-h;
if(x<0) x=0;
if(y<0) y=0;
/* find the threshold value to differentiate between dark and light */
do {
thresh_lum = MAXRGB * new_thresh;
old_thresh = new_thresh;
size_black = sum_black = size_white = sum_white = 0;
for(xi=0; (xi<w) && (xi<width); xi++) {
for(yi=0; (yi<h) && (yi<height); yi++) {
for(xi=0; xi<width; xi++) {
for(yi=0; yi<height; yi++) {
imlib_image_query_pixel(xi, yi, &color);
lum = get_lum(&color, lt);
if(lum <= thresh_lum) {
@@ -604,92 +608,39 @@ double iterative_threshold(Imlib_Image *source_image, double thresh,
return new_thresh * 100;
}
/* get minimum lum value */
double get_minval(Imlib_Image *source_image, int x, int y, int w, int h,
luminance_t lt)
/* get minimum and maximum lum values */
void get_minmaxval(Imlib_Image *source_image, luminance_t lt,
double *min, double *max)
{
Imlib_Image current_image; /* save image pointer */
int height, width; /* image dimensions */
int w, h; /* image dimensions */
int xi,yi; /* iteration variables */
Imlib_Color color; /* Imlib2 RGBA color structure */
int minval = MAXRGB;
int lum = 0;
*min = MAXRGB;
*max = 0;
/* save pointer to current image */
current_image = imlib_context_get_image();
/* get image dimensions */
imlib_context_set_image(*source_image);
height = imlib_image_get_height();
width = imlib_image_get_width();
/* special value -1 for width or height means image width/height */
if(w == -1) w = width;
if(h == -1) h = width;
/* assure valid coordinates */
if(x+w > width) x = width-w;
if(y+h > height) y = height-h;
if(x<0) x=0;
if(y<0) y=0;
h = imlib_image_get_height();
w = imlib_image_get_width();
/* find the minimum value in the image */
for(xi=0; (xi<w) && (xi<width); xi++) {
for(yi=0; (yi<h) && (yi<height); yi++) {
for(xi=0; xi<w; xi++) {
for(yi=0; yi<h; yi++) {
imlib_image_query_pixel(xi, yi, &color);
lum = clip(get_lum(&color, lt),0,255);
if(lum < minval) minval = lum;
if(lum < *min) *min = lum;
if(lum > *max) *max = lum;
}
}
/* restore image from before function call */
imlib_context_set_image(current_image);
return minval;
}
/* get maximum luminance value */
double get_maxval(Imlib_Image *source_image, int x, int y, int w, int h,
luminance_t lt)
{
Imlib_Image current_image; /* save image pointer */
int height, width; /* image dimensions */
int xi,yi; /* iteration variables */
Imlib_Color color; /* Imlib2 RGBA color structure */
int lum = 0;
int maxval = 0;
/* save pointer to current image */
current_image = imlib_context_get_image();
/* get image dimensions */
imlib_context_set_image(*source_image);
height = imlib_image_get_height();
width = imlib_image_get_width();
/* special value -1 for width or height means image width/height */
if(w == -1) w = width;
if(h == -1) h = width;
/* assure valid coordinates */
if(x+w > width) x = width-w;
if(y+h > height) y = height-h;
if(x<0) x=0;
if(y<0) y=0;
/* find the minimum value in the image */
for(xi=0; (xi<w) && (xi<width); xi++) {
for(yi=0; (yi<h) && (yi<height); yi++) {
imlib_image_query_pixel(xi, yi, &color);
lum = clip(get_lum(&color, lt),0,255);
if(lum > maxval) maxval = lum;
}
}
/* restore image from before function call */
imlib_context_set_image(current_image);
return maxval;
}
/* draw a white (background) border around image, overwriting image contents
@@ -757,15 +708,11 @@ Imlib_Image shear(Imlib_Image *source_image, int offset)
/* copy pixels */
for(x=width-1; x>=shift; x--) {
imlib_image_query_pixel(x-shift, y, &color_return);
imlib_context_set_image(new_image);
imlib_context_set_color(color_return.red, color_return.green,
color_return.blue, color_return.alpha);
imlib_image_draw_pixel(x,y,0);
imlib_context_set_image(*source_image);
draw_color_pixel(&new_image, x, y, color_return);
}
/* fill with background */
for(x=0; x<shift; x++) {
draw_bg_pixel(new_image, x, y);
draw_bg_pixel(&new_image, x, y);
}
}
@@ -806,14 +753,10 @@ Imlib_Image rotate(Imlib_Image *source_image, double theta)
sy = (y-height/2) * cos(theta) - (x-width/2) * sin(theta) + height/2;
if((sx >= 0) && (sx <= width) && (sy >= 0) && (sy <= height)) {
imlib_image_query_pixel(sx, sy, &c);
imlib_context_set_image(new_image);
imlib_context_set_color(c.red, c.green, c.blue, c.alpha);
draw_color_pixel(&new_image, x, y, c);
} else {
imlib_context_set_image(new_image);
ssocr_set_color(BG);
draw_bg_pixel(&new_image, x, y);
}
imlib_image_draw_pixel(x,y,0);
imlib_context_set_image(*source_image);
}
}
@@ -847,20 +790,14 @@ Imlib_Image mirror(Imlib_Image *source_image, direction_t direction)
for(x = width-1; x>=0; x--) {
for(y = 0; y < height; y++) {
imlib_image_query_pixel(width - 1 - x, y, &c);
imlib_context_set_image(new_image);
imlib_context_set_color(c.red, c.green, c.blue, c.alpha);
imlib_image_draw_pixel(x,y,0);
imlib_context_set_image(*source_image);
draw_color_pixel(&new_image, x, y, c);
}
}
} else if(direction == VERTICAL) {
for(x = 0; x < width; x++) {
for(y = height-1; y >= 0; y--) {
imlib_image_query_pixel(x, height - 1 - y, &c);
imlib_context_set_image(new_image);
imlib_context_set_color(c.red, c.green, c.blue, c.alpha);
imlib_image_draw_pixel(x,y,0);
imlib_context_set_image(*source_image);
draw_color_pixel(&new_image, x, y, c);
}
}
}
@@ -935,9 +872,9 @@ Imlib_Image invert(Imlib_Image *source_image, double thresh, luminance_t lt)
imlib_image_query_pixel(x, y, &color);
lum = get_lum(&color, lt);
if(is_pixel_set(lum, thresh)) {
draw_bg_pixel(new_image, x, y);
draw_bg_pixel(&new_image, x, y);
} else {
draw_fg_pixel(new_image, x, y);
draw_fg_pixel(&new_image, x, y);
}
}
}
@@ -1126,7 +1063,7 @@ luminance_t parse_lum(char *keyword)
} else if(strcasecmp(keyword, "blue") == 0) {
return BLUE;
} else {
return DEFAULT_LUM_FORMULA;
return LUM_PARSE_ERROR;
}
}
+11 -12
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2004-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2004-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
#ifndef SSOCR2_IMGPROC_H
#define SSOCR2_IMGPROC_H
@@ -32,7 +32,7 @@ void set_bg_color(int color);
void ssocr_set_color(fg_bg_t color);
/* draw a fore- or background pixel */
void draw_pixel(Imlib_Image *image, int x, int y, fg_bg_t color);
void draw_fg_bg_pixel(Imlib_Image *image, int x, int y, fg_bg_t color);
/* draw a foreground pixel */
void draw_fg_pixel(Imlib_Image *image, int x, int y);
@@ -40,6 +40,9 @@ void draw_fg_pixel(Imlib_Image *image, int x, int y);
/* draw a background pixel */
void draw_bg_pixel(Imlib_Image *image, int x, int y);
/* draw a pixel of a given color */
void draw_color_pixel(Imlib_Image *image, int x, int y, Imlib_Color color);
/* check if a pixel is set regarding current foreground/background colors */
int is_pixel_set(int value, double threshold);
@@ -126,8 +129,8 @@ Imlib_Image grayscale(Imlib_Image *source_image, luminance_t lt);
Imlib_Image crop(Imlib_Image *source_image, int x, int y, int w, int h);
/* adapt threshold to image values values */
double adapt_threshold(Imlib_Image *image, double thresh, luminance_t lt, int x,
int y, int w, int h, unsigned int flags);
double adapt_threshold(Imlib_Image *image, double thresh, luminance_t lt,
unsigned int flags, int force_update);
/* compute dynamic threshold value from the rectangle (x,y),(x+w,y+h) of
* source_image */
@@ -136,15 +139,11 @@ double get_threshold(Imlib_Image *source_image, double fraction, luminance_t lt,
/* determine threshold by an iterative method */
double iterative_threshold(Imlib_Image *source_image, double thresh,
luminance_t lt, int x, int y, int w, int h);
luminance_t lt);
/* get minimum gray value */
double get_minval(Imlib_Image *source_image, int x, int y, int w, int h,
luminance_t lt);
/* get maximum gray value */
double get_maxval(Imlib_Image *source_image, int x, int y, int w, int h,
luminance_t lt);
/* get minimum and maximum gray (luminace) values */
void get_minmaxval(Imlib_Image *source_image, luminance_t lt,
double *min, double *max);
/* compute luminance from RGB values */
int get_lum(Imlib_Color *color, luminance_t lt);
+1 -1
View File
@@ -12,7 +12,7 @@ Upstream Author(s):
Copyright:
Copyright (C) 2004-2022 Erik Auerswald
Copyright (C) 2004-2025 Erik Auerswald
License:
+114 -11
View File
@@ -1,4 +1,4 @@
.TH ssocr 1 "@DATE@" @VERSION@ "OCR for seven segment displays"
.TH ssocr 1 "@DATE@" "@VERSION@" "OCR for seven segment displays"
.SH NAME
ssocr \- optical recognition of seven segment displays
.SH SYNOPSIS
@@ -13,6 +13,29 @@ Use
as file name to read the image from standard input.
.B ssocr
provides several image manipulation algorithms to enhance noisy images.
.PP
.B Options
can be used to change
.B ssocr
behavior.
.PP
.B Commands
can be used to manipulate the input
.I IMAGE
before starting the recognition algorithm.
.PP
Two hyphens
.RB ( \-\- )
can be used as a special argument to end option-scanning, e.g.,
in order to use a negative number as argument to a command.
.PP
When using a single character (i.e., short) option,
arguments can either directly follow the option character,
or can be separated from the option character by whitespace.
When using a multi character (i.e., long) option,
arguments must be separated from the option by either an equals sign
.RB ( = ),
or whitespace.
.SH OPTIONS
.SS \-h, \-\-help
Write a help message to standard output.
@@ -30,53 +53,113 @@ is used. The default threshold is
.IR 50 .
.SS \-a, \-\-absolute\-threshold
Do not adjust the threshold to the luminance values occurring in the image.
Using this option also inhibits iterative thresholding using option
.BR \-\-iter\-threshold .
Consider this option when using the
.B dynamic_threshold
command.
or
.B gray_stretch
commands.
.SS \-T, \-\-iter\-threshold
Use an iterative method (one-dimensional k-means clustering) to determine the
threshold. The starting value can be specified with the
.B \-\-threshold
option.
Option
.B \-\-absolute\-threshold
inhibits iterative threshold determination.
.SS \-n, \-\-number\-pixels NUMBER
Set the number of foreground pixels that have to be found in a scanline to
recognize a segment.
This does not apply to ratio based recognition.
Can be used to ignore some noise in the picture.
See the web page of
.BR ssocr (1)
for a description of the algorithm.
.SS \-N, \-\-min\-segment SIZE
Set the minimum number of pixels required for width and height of an individual
segment of a seven segment display.
A set segment in the display must have both a width and height of at least
.B SIZE
pixels.
This minimum is used for both scanline based and ratio based recognition.
It is not applied to decimal separator detection,
because those are not comprised of regular segments.
This option can be used to ignore some noise in the picture.
See the web page of
.BR ssocr (1)
for a description of the algorithm.
.SS \-i, \-\-ignore\-pixels NUMBER
Set the number of foreground pixels that are ignored when deciding if a column
consists only of background or foreground pixels.
or row consists only of background or foreground pixels.
Can be used to ignore some noise in the picture.
See the web page of
.BR ssocr (1)
for a description of the algorithm.
.SS \-d, \-\-number\-digits NUMBER
.SS \-M, \-\-min\-char\-dims WIDTHxHEIGHT
Specify the minimum dimensions of characters respectively digits.
When the segmentation step finds potential digits,
those with a width less than
.B WIDTH
or a height less than
.B HEIGHT
are ignored.
Can be used to ignore some noise in the picture.
See the web page of
.BR ssocr (1)
for a description of the algorithm.
.SS \-d, \-\-number\-digits RANGE
Specifies the number of digits shown in the image. Default value is
.IR 6 .
Use
.I \-1
to automatically detect the number of digits.
Use a single positive number to specify an exact number of digits.
Use two positive numbers separated with a hyphen
.RI ( - )
to specify an inclusive range of acceptable values for the number of digits.
.SS \-r, \-\-one\-ratio RATIO
Set the height/width ratio threshold to recognize a digit as a one.
RATIO takes integers only.
A digit with a height/width ratio greater than
.B RATIO
is recognized as a one.
.B RATIO
takes integers only.
See the web page of
.BR ssocr (1)
for a description of the algorithm.
.SS \-m, \-\-minus\-ratio RATIO
Set the width/height ratio to recognize a minus sign.
A digit with a width/height ratio greater than or equal to
.B RATIO
is recognized as a minus sign.
.B RATIO
takes integers only.
This uses the same idea as recognizing the digit one.
.SS \-H, \-\-dec\-h\-ratio RATIO
Set the max_digit_height/height ratio used for recognition of a decimal
separator.
.B RATIO
takes integers only.
This value is used in combination with the max_digit_width/width ratio.
If the height of a digit is less than
.RB 1/ RATIO
of the maximum digit height in the image and the max_digit_width/width
threshold is also reached,
it is recognized as a decimal separator.
.SS \-W, \-\-dec\-w\-ratio RATIO
Set the max_digit_width/width ratio used for recognition of a decimal
separator.
Set the max_digit_width/width ratio used for recognition of a decimal separator.
.B RATIO
takes integers only.
This value is used in combination with the max_digit_height/height ratio.
If the width of a digit is less than
.RB 1/ RATIO
of the maximum digit width in the image
and the max_digit_height/height threshold is also reached,
it is recognized as a decimal separator.
.SS \-o, \-\-output\-image FILE
Write the processed image to FILE.
Write the processed image to
.BR FILE .
Use
.B \-
to write to standard output.
@@ -155,7 +238,8 @@ The default of
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).
than a factor times the minimum (default) or average distance between digits
(characters).
.SS \-A, \-\-space\-factor FACTOR
Use the given
.B FACTOR
@@ -213,7 +297,20 @@ of the included characters.
The default is
.I full
(recognizing all characters known to ssocr in the image).
.SS \-F, \-\-adapt\-after\-crop
When using the
.B crop
command,
adjust (adapt) the threshold to image luminance values only after cropping,
not also directly before.
Using other commands before
.B crop
can still lead to adapting the threshold to the original image.
.SH COMMANDS
Most commands do not change the image dimensions.
The
.B crop
command is a notable exception to this rule.
.SS dilation [N]
Filter image using dilation algorithm.
Any pixel with at least one neighbour pixel set in the source image will be
@@ -293,8 +390,13 @@ the values
and
.B T2
are interpreted as percentages.
Consider using the
.B \-\-absolute\-threshold
option together with a manually adjusted
.B \-\-threshold
for predictable results.
.SS dynamic_threshold W H
Convert the image to monochrome using dynamic thresholding a.k.a local
Convert the image to monochrome using dynamic thresholding a.k.a. local
adaptive thresholding.
A window of width
.B W
@@ -355,7 +457,7 @@ or
.B dynamic_threshold
instead.
.SS white_border [WIDTH]
The border of the image is set to the foreground color.
The border of the image is set to the background color.
This border is one pixel wide unless a
.B WIDTH
>
@@ -395,6 +497,7 @@ Use only the subpicture with upper left corner (
.B W
and height
.BR H .
This command changes the image dimensions.
.SS set_pixels_filter MASK
Set every pixel in the filtered image that has at least
.B MASK
+475 -115
View File
File diff suppressed because it is too large Load Diff
+9 -1
View File
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Copyright (C) 2004-2022 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
/* Copyright (C) 2004-2025 Erik Auerswald <auerswal@unix-ag.uni-kl.de> */
#ifndef SSOCR2_H
#define SSOCR2_H
@@ -27,4 +27,12 @@ typedef struct {
int R, G, B, A;
} color_struct;
typedef struct {
int w, h;
} dimensions_struct;
typedef struct {
int min, max;
} interval_struct;
#endif /* SSOCR2_H */