Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 443b100ab9 | |||
| 63495ef4a8 | |||
| 9d9b2253e1 | |||
| e914669079 | |||
| 94ce321060 | |||
| 7cae796188 | |||
| 7f2a9f3f22 | |||
| 00312ee70e | |||
| e309861f24 | |||
| 4b5c6ea770 | |||
| 56d1b22118 | |||
| eaf0f32850 | |||
| fa30f473e7 | |||
| 67abe0fba8 | |||
| ac060de96b | |||
| 74aeb44f94 | |||
| f012c14d93 | |||
| b44a4ad72a | |||
| 13a5ec3802 | |||
| 2824d0aea7 |
@@ -1,6 +1,22 @@
|
||||
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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2018-2024 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 */
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2018-2024 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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2004-2024 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.24.1"
|
||||
#define VERSION "2.25.1"
|
||||
|
||||
/* states */
|
||||
#define FIND_DARK 0
|
||||
@@ -156,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
|
||||
@@ -172,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,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2004-2024 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,7 +92,7 @@ void print_version(FILE *f)
|
||||
{
|
||||
fprintf(f, "Seven Segment Optical Character Recognition Version %s\n",
|
||||
VERSION);
|
||||
fprintf(f, "Copyright (C) 2004-2024 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 is free software, and you are welcome to redistribute it"
|
||||
@@ -151,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");
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2004-2024 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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2004-2024 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2004-2024 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
@@ -12,7 +12,7 @@ Upstream Author(s):
|
||||
|
||||
Copyright:
|
||||
|
||||
Copyright (C) 2004-2024 Erik Auerswald
|
||||
Copyright (C) 2004-2025 Erik Auerswald
|
||||
|
||||
License:
|
||||
|
||||
|
||||
+23
-2
@@ -53,14 +53,21 @@ 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.
|
||||
@@ -290,6 +297,15 @@ 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
|
||||
@@ -374,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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2004-2024 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> */
|
||||
|
||||
/* ImLib2 Header */
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
/* option parsing */
|
||||
#include <getopt.h> /* getopt */
|
||||
#include <unistd.h> /* getopt */
|
||||
#include <unistd.h> /* getopt, read, write, STDIN_FILENO */
|
||||
|
||||
/* file permissions */
|
||||
#include <sys/stat.h> /* umask */
|
||||
@@ -57,8 +57,8 @@ static char * tmp_imgfile(unsigned int flags)
|
||||
char *name;
|
||||
size_t pattern_len;
|
||||
int handle;
|
||||
unsigned char buf;
|
||||
ssize_t count = 0;
|
||||
unsigned char buf[BUFSIZ];
|
||||
ssize_t read_count = 0, write_count = 0;
|
||||
size_t pat_suffix_len = strlen(DIR_SEP TMP_FILE_PATTERN);
|
||||
size_t dir_len;
|
||||
|
||||
@@ -99,12 +99,16 @@ static char * tmp_imgfile(unsigned int flags)
|
||||
}
|
||||
|
||||
/* copy image data from stdin to tmp file */
|
||||
while((fread(&buf, sizeof(char), 1, stdin)) > 0) {
|
||||
count = write(handle, &buf, 1);
|
||||
if (count <= 0) break;
|
||||
while((read_count = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
|
||||
write_count = write(handle, buf, read_count);
|
||||
if (write_count <= 0) break;
|
||||
}
|
||||
close(handle); /* filehandle is no longer needed, Imlib2 uses filename */
|
||||
if(ferror(stdin) || (count <= 0)) {
|
||||
if(read_count < 0) {
|
||||
perror(PROG ": could not read image from standard input");
|
||||
exit(99);
|
||||
}
|
||||
if(write_count <= 0) {
|
||||
perror(PROG ": could not copy image data to temporary file");
|
||||
unlink(name);
|
||||
exit(99);
|
||||
@@ -114,16 +118,20 @@ static char * tmp_imgfile(unsigned int flags)
|
||||
}
|
||||
|
||||
/* return number of foreground pixels in a scanline */
|
||||
static unsigned int scanline(Imlib_Image *image, Imlib_Image *debug_image,
|
||||
static unsigned int scanline(Imlib_Image *debug_image,
|
||||
int x, int y, int len, direction_t dir,
|
||||
color_struct d_color, double thresh,
|
||||
luminance_t lt, unsigned int flags)
|
||||
{
|
||||
Imlib_Color imlib_color;
|
||||
Imlib_Color imlib_color, debug_color;
|
||||
int lum, i, ix=x, iy=y, start, end;
|
||||
unsigned int found_pixels = 0;
|
||||
start = (dir == HORIZONTAL) ? x : y;
|
||||
end = start + len;
|
||||
debug_color.red = d_color.R;
|
||||
debug_color.green = d_color.G;
|
||||
debug_color.blue = d_color.B;
|
||||
debug_color.alpha = d_color.A;
|
||||
for (i = start; i <= end; i++) {
|
||||
if (dir == HORIZONTAL) ix = i;
|
||||
else iy = i;
|
||||
@@ -131,10 +139,7 @@ static unsigned int scanline(Imlib_Image *image, Imlib_Image *debug_image,
|
||||
lum = get_lum(&imlib_color, lt);
|
||||
if(is_pixel_set(lum, thresh)) {
|
||||
if(flags & USE_DEBUG_IMAGE) {
|
||||
imlib_context_set_image(*debug_image);
|
||||
imlib_context_set_color(d_color.R, d_color.G, d_color.B, d_color.A);
|
||||
imlib_image_draw_pixel(ix, iy, 0);
|
||||
imlib_context_set_image(*image);
|
||||
draw_color_pixel(debug_image, ix, iy, debug_color);
|
||||
}
|
||||
found_pixels++;
|
||||
}
|
||||
@@ -334,10 +339,11 @@ int main(int argc, char **argv)
|
||||
{"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 */
|
||||
{"adapt-after-crop", 0, 0, 'F'}, /* don't adapt threshold before crop */
|
||||
{0, 0, 0, 0} /* terminate long options */
|
||||
};
|
||||
c = getopt_long (argc, argv,
|
||||
"hVt:vaTn:N:i:d:r:m:M:o:O:D::pPf:b:Igl:SXCc:H:W:sA:G",
|
||||
"hVt:vaTn:N:i:d:r:m:M:o:O:D::pPf:b:Igl:SXCc:H:W:sA:GF",
|
||||
long_options, &option_index);
|
||||
if (c == -1) break; /* leaves while (1) loop */
|
||||
switch (c) {
|
||||
@@ -618,6 +624,13 @@ int main(int argc, char **argv)
|
||||
flags & SPC_USE_AVG_DST);
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
flags |= ADAPT_AFTER_CROP;
|
||||
if(flags & DEBUG_OUTPUT) {
|
||||
fprintf(stderr, "flags & ADAPT_AFTER_CROP=%d\n",
|
||||
flags & ADAPT_AFTER_CROP);
|
||||
}
|
||||
break;
|
||||
case '?': /* missing argument or character not in optstring */
|
||||
short_usage(PROG,stderr);
|
||||
exit (2);
|
||||
@@ -634,6 +647,8 @@ int main(int argc, char **argv)
|
||||
exit(99);
|
||||
}
|
||||
}
|
||||
if((flags & ABSOLUTE_THRESHOLD) && (flags & DO_ITERATIVE_THRESHOLD))
|
||||
fprintf(stderr, "%s: warning: -T has no effect due to -a\n", PROG);
|
||||
if(flags & DEBUG_OUTPUT) {
|
||||
fprintf(stderr, "================================================================================\n");
|
||||
fprintf(stderr, "VERSION=%s\n", VERSION);
|
||||
@@ -652,6 +667,7 @@ int main(int argc, char **argv)
|
||||
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, "flags & ADAPT_AFTER_CROP=%d\n", flags & ADAPT_AFTER_CROP);
|
||||
fprintf(stderr, "need_pixels = %d\n", need_pixels);
|
||||
fprintf(stderr, "min_segment = %d\n", min_segment);
|
||||
fprintf(stderr, "min_char_dims = %dx%d\n",min_char_dims.w,min_char_dims.h);
|
||||
@@ -722,14 +738,12 @@ int main(int argc, char **argv)
|
||||
|
||||
/* get minimum and maximum "value" values */
|
||||
if((flags & DEBUG_OUTPUT) || (flags & PRINT_INFO)) {
|
||||
double min, max;
|
||||
get_minmaxval(&image, lt, &min, &max);
|
||||
fprintf(stderr, "%.2f <= lum <= %.2f (lum should be in [0,255])\n",
|
||||
get_minval(&image, 0, 0, -1, -1, lt),
|
||||
get_maxval(&image, 0, 0, -1, -1, lt));
|
||||
min, max);
|
||||
}
|
||||
|
||||
/* adapt threshold to image */
|
||||
thresh = adapt_threshold(&image, thresh, lt, 0, 0, -1, -1, flags);
|
||||
|
||||
/* process commands */
|
||||
if(flags & VERBOSE) /* then print found commands */ {
|
||||
if(optind >= argc-1) {
|
||||
@@ -759,11 +773,12 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
i++;
|
||||
new_image = dilation(&image, thresh, lt, n);
|
||||
} else {
|
||||
n = 1;
|
||||
if(flags & VERBOSE) fputs(" processing dilation (1)\n", stderr);
|
||||
new_image = dilation(&image, thresh, lt, 1);
|
||||
}
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = dilation(&image, thresh, lt, n);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
@@ -778,11 +793,12 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
i++;
|
||||
new_image = erosion(&image, thresh, lt, n);
|
||||
} else {
|
||||
n = 1;
|
||||
if(flags & VERBOSE) fputs(" processing erosion (1)\n", stderr);
|
||||
new_image = erosion(&image, thresh, lt, 1);
|
||||
}
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = erosion(&image, thresh, lt, n);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
@@ -797,11 +813,12 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
i++;
|
||||
new_image = opening(&image, thresh, lt, n);
|
||||
} else {
|
||||
n = 1;
|
||||
if(flags & VERBOSE) fputs(" processing opening (1)\n", stderr);
|
||||
new_image = opening(&image, thresh, lt, 1);
|
||||
}
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = opening(&image, thresh, lt, n);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
@@ -816,22 +833,25 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
i++;
|
||||
new_image = closing(&image, thresh, lt, n);
|
||||
} else {
|
||||
n = 1;
|
||||
if(flags & VERBOSE) fputs(" processing closing (1)\n", stderr);
|
||||
new_image = closing(&image, thresh, lt, 1);
|
||||
}
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = closing(&image, thresh, lt, n);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
} else if(strcasecmp("remove_isolated",argv[i]) == 0) {
|
||||
if(flags & VERBOSE) fputs(" processing remove_isolated\n", stderr);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = remove_isolated(&image, thresh, lt);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
} else if(strcasecmp("make_mono",argv[i]) == 0) {
|
||||
if(flags & VERBOSE) fputs(" processing make_mono\n", stderr);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = make_mono(&image, thresh, lt);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -846,13 +866,14 @@ int main(int argc, char **argv)
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
new_image = white_border(&image, bdwidth);
|
||||
i++;
|
||||
} else {
|
||||
bdwidth = 1;
|
||||
if(flags & VERBOSE)
|
||||
fputs(" processing white_border (1)\n", stderr);
|
||||
new_image = white_border(&image, 1);
|
||||
}
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = white_border(&image, bdwidth);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
@@ -866,6 +887,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if(i+1<argc-1) {
|
||||
offset = (int) atoi(argv[++i]); /* sideeffect: increment i */
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = shear(&image, offset);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -885,6 +907,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if(i+1<argc-1) {
|
||||
mask = (int) atoi(argv[++i]); /* sideeffect: increment i */
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = set_pixels_filter(&image, thresh, lt, mask);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -905,6 +928,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
if(i+1<argc-1) {
|
||||
mask = (int) atoi(argv[++i]); /* sideeffect: increment i */
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = keep_pixels_filter(&image, thresh, lt, mask);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -927,6 +951,7 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
i+=2; /* skip the arguments to dynamic_threshold */
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = dynamic_threshold(&image, thresh, lt, ww, wh);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -938,30 +963,35 @@ int main(int argc, char **argv)
|
||||
}
|
||||
} else if(strcasecmp("rgb_threshold",argv[i]) == 0) {
|
||||
if(flags & VERBOSE) fputs(" processing rgb_threshold\n", stderr);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = make_mono(&image, thresh, MINIMUM);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
} else if(strcasecmp("r_threshold",argv[i]) == 0) {
|
||||
if(flags & VERBOSE) fputs(" processing r_threshold\n", stderr);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = make_mono(&image, thresh, RED);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
} else if(strcasecmp("g_threshold",argv[i]) == 0) {
|
||||
if(flags & VERBOSE) fputs(" processing g_threshold\n", stderr);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = make_mono(&image, thresh, GREEN);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
} else if(strcasecmp("b_threshold",argv[i]) == 0) {
|
||||
if(flags & VERBOSE) fputs(" processing b_threshold\n", stderr);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = make_mono(&image, thresh, BLUE);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
image = new_image;
|
||||
} else if(strcasecmp("invert",argv[i]) == 0) {
|
||||
if(flags & VERBOSE) fputs(" processing invert\n", stderr);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = invert(&image, thresh, lt);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -984,8 +1014,7 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, " adjusting T1=%.2f and T2=%.2f to image\n",
|
||||
t1, t2);
|
||||
}
|
||||
min = get_minval(&image, 0, 0, -1, -1, lt);
|
||||
max = get_maxval(&image, 0, 0, -1, -1, lt);
|
||||
get_minmaxval(&image, lt, &min, &max);
|
||||
t1 = min + t1/100.0 * (max - min);
|
||||
t2 = min + t2/100.0 * (max - min);
|
||||
if(flags & VERBOSE) {
|
||||
@@ -993,6 +1022,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
i+=2; /* skip the arguments to gray_stretch */
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = gray_stretch(&image, t1, t2, lt);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -1010,7 +1040,7 @@ int main(int argc, char **argv)
|
||||
image = new_image;
|
||||
} else if(strcasecmp("crop",argv[i]) == 0) {
|
||||
if(i+4<argc-1) {
|
||||
int x, y, cw, ch; /* lw = crop width, lh = crop height */
|
||||
int x, y, cw, ch; /* cw = crop width, ch = crop height */
|
||||
x = atoi(argv[i+1]);
|
||||
y = atoi(argv[i+2]);
|
||||
cw = atoi(argv[i+3]);
|
||||
@@ -1026,7 +1056,8 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
i += 4; /* skip the arguments to crop */
|
||||
imlib_context_set_image(image);
|
||||
if(!(flags & ADAPT_AFTER_CROP))
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = crop(&image, x, y, cw, ch);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -1041,13 +1072,13 @@ int main(int argc, char **argv)
|
||||
}
|
||||
/* get minimum and maximum "value" values in cropped image */
|
||||
if((flags&DEBUG_OUTPUT) || (flags&PRINT_INFO) || (flags&VERBOSE)) {
|
||||
double min, max;
|
||||
get_minmaxval(&image, lt, &min, &max);
|
||||
fprintf(stderr, " %.2f <= lum <= %.2f in cropped image"
|
||||
" (lum should be in [0,255])\n",
|
||||
get_minval(&image, 0, 0, -1, -1, lt),
|
||||
get_maxval(&image, 0, 0, -1, -1, lt));
|
||||
" (lum should be in [0,255])\n", min, max);
|
||||
}
|
||||
/* adapt threshold to cropped image */
|
||||
thresh = adapt_threshold(&image, thresh, lt, 0, 0, -1, -1, flags);
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, UPDATE);
|
||||
} else {
|
||||
fprintf(stderr, "%s: error: crop command needs 4 arguments\n", PROG);
|
||||
exit(99);
|
||||
@@ -1062,6 +1093,7 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
theta = atof(argv[++i]); /* sideeffect: increment i */
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
new_image = rotate(&image, theta);
|
||||
imlib_context_set_image(image);
|
||||
imlib_free_image();
|
||||
@@ -1111,6 +1143,9 @@ int main(int argc, char **argv)
|
||||
/* exit if only image processing shall be done */
|
||||
if(flags & PROCESS_ONLY) exit(3);
|
||||
|
||||
/* adapt threshold to image (unless this is already done) */
|
||||
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
|
||||
|
||||
if(flags & USE_DEBUG_IMAGE) {
|
||||
/* copy processed image to debug image */
|
||||
debug_image = make_mono(&image, thresh, lt);
|
||||
@@ -1607,14 +1642,14 @@ int main(int argc, char **argv)
|
||||
/* check horizontal segments (vertical scan, x == middle) */
|
||||
d_color.R = d_color.A = 255;
|
||||
d_color.G = d_color.B = 0;
|
||||
found_pixels = scanline(&image, &debug_image, middle, digits[d].y1,
|
||||
found_pixels = scanline(&debug_image, middle, digits[d].y1,
|
||||
d_height/3, VERTICAL, d_color, thresh, lt, flags);
|
||||
if(found_pixels >= need_pixels) {
|
||||
digits[d].digit |= HORIZ_UP; /* add upper segment */
|
||||
}
|
||||
d_color.G = d_color.A = 255;
|
||||
d_color.R = d_color.B = 0;
|
||||
found_pixels = scanline(&image, &debug_image, middle,
|
||||
found_pixels = scanline(&debug_image, middle,
|
||||
digits[d].y1 + d_height/3, d_height/3, VERTICAL,
|
||||
d_color, thresh, lt, flags);
|
||||
if(found_pixels >= need_pixels) {
|
||||
@@ -1622,7 +1657,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
d_color.B = d_color.A = 255;
|
||||
d_color.R = d_color.G = 0;
|
||||
found_pixels = scanline(&image, &debug_image, middle,
|
||||
found_pixels = scanline(&debug_image, middle,
|
||||
digits[d].y1 + 2*d_height/3, d_height/3, VERTICAL,
|
||||
d_color, thresh, lt, flags);
|
||||
if(found_pixels >= need_pixels) {
|
||||
@@ -1631,7 +1666,7 @@ int main(int argc, char **argv)
|
||||
/* check upper vertical segments (horizontal scan, y == quarter) */
|
||||
d_color.R = d_color.A = 255;
|
||||
d_color.G = d_color.B = 0;
|
||||
found_pixels = scanline(&image, &debug_image, digits[d].x1, quarter,
|
||||
found_pixels = scanline(&debug_image, digits[d].x1, quarter,
|
||||
(digits[d].x2 - digits[d].x1) / 2, HORIZONTAL,
|
||||
d_color, thresh, lt, flags);
|
||||
if (found_pixels >= need_pixels) {
|
||||
@@ -1639,7 +1674,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
d_color.G = d_color.A = 255;
|
||||
d_color.R = d_color.B = 0;
|
||||
found_pixels = scanline(&image, &debug_image,
|
||||
found_pixels = scanline(&debug_image,
|
||||
(digits[d].x1 + digits[d].x2) / 2 + 1,
|
||||
quarter, (digits[d].x2 - digits[d].x1) / 2 - 1,
|
||||
HORIZONTAL, d_color, thresh, lt, flags);
|
||||
@@ -1649,7 +1684,7 @@ int main(int argc, char **argv)
|
||||
/* check lower vertical segments (horizontal scan, y == three_quarters) */
|
||||
d_color.R = d_color.A = 255;
|
||||
d_color.G = d_color.B = 0;
|
||||
found_pixels = scanline(&image, &debug_image, digits[d].x1,
|
||||
found_pixels = scanline(&debug_image, digits[d].x1,
|
||||
three_quarters, (digits[d].x2 - digits[d].x1) / 2,
|
||||
HORIZONTAL, d_color, thresh, lt, flags);
|
||||
if (found_pixels >= need_pixels) {
|
||||
@@ -1657,7 +1692,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
d_color.G = d_color.A = 255;
|
||||
d_color.R = d_color.B = 0;
|
||||
found_pixels = scanline(&image, &debug_image,
|
||||
found_pixels = scanline(&debug_image,
|
||||
(digits[d].x1 + digits[d].x2) / 2 + 1,
|
||||
three_quarters, (digits[d].x2-digits[d].x1)/2 - 1,
|
||||
HORIZONTAL, d_color, thresh, lt, flags);
|
||||
|
||||
Reference in New Issue
Block a user