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.
This commit is contained in:
Erik Auerswald
2025-03-23 14:42:25 +01:00
parent 7cae796188
commit 94ce321060
5 changed files with 36 additions and 7 deletions
+2
View File
@@ -7,6 +7,8 @@ Version ?.??.? (????-??-??):
--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):
+4
View File
@@ -172,6 +172,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,
+6 -2
View File
@@ -466,10 +466,13 @@ 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,
unsigned int flags)
unsigned int flags, int force_update)
{
double t = thresh;
if(!(flags & ABSOLUTE_THRESHOLD)) {
static int is_adapted = 0;
if(is_adapted && !force_update) {
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, 0, 0, -1, -1);
@@ -482,6 +485,7 @@ double adapt_threshold(Imlib_Image *image, double thresh, luminance_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);
+1 -1
View File
@@ -130,7 +130,7 @@ 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,
unsigned int flags);
unsigned int flags, int force_update);
/* compute dynamic threshold value from the rectangle (x,y),(x+w,y+h) of
* source_image */
+23 -4
View File
@@ -735,9 +735,6 @@ int main(int argc, char **argv)
min, max);
}
/* adapt threshold to image */
thresh = adapt_threshold(&image, thresh, lt, flags);
/* process commands */
if(flags & VERBOSE) /* then print found commands */ {
if(optind >= argc-1) {
@@ -771,6 +768,7 @@ int main(int argc, char **argv)
n = 1;
if(flags & VERBOSE) fputs(" processing dilation (1)\n", stderr);
}
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
new_image = dilation(&image, thresh, lt, n);
imlib_context_set_image(image);
imlib_free_image();
@@ -790,6 +788,7 @@ int main(int argc, char **argv)
n = 1;
if(flags & VERBOSE) fputs(" processing erosion (1)\n", stderr);
}
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
new_image = erosion(&image, thresh, lt, n);
imlib_context_set_image(image);
imlib_free_image();
@@ -809,6 +808,7 @@ int main(int argc, char **argv)
n = 1;
if(flags & VERBOSE) fputs(" processing opening (1)\n", stderr);
}
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
new_image = opening(&image, thresh, lt, n);
imlib_context_set_image(image);
imlib_free_image();
@@ -828,18 +828,21 @@ int main(int argc, char **argv)
n = 1;
if(flags & VERBOSE) fputs(" processing closing (1)\n", stderr);
}
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();
@@ -860,6 +863,7 @@ int main(int argc, char **argv)
if(flags & VERBOSE)
fputs(" processing white_border (1)\n", stderr);
}
thresh = adapt_threshold(&image, thresh, lt, flags, INITIAL);
new_image = white_border(&image, bdwidth);
imlib_context_set_image(image);
imlib_free_image();
@@ -874,6 +878,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();
@@ -893,6 +898,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();
@@ -913,6 +919,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();
@@ -935,6 +942,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();
@@ -946,30 +954,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();
@@ -1000,6 +1013,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();
@@ -1033,6 +1047,7 @@ int main(int argc, char **argv)
fprintf(stderr, "\n");
}
i += 4; /* skip the arguments to 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();
@@ -1053,7 +1068,7 @@ int main(int argc, char **argv)
" (lum should be in [0,255])\n", min, max);
}
/* adapt threshold to cropped image */
thresh = adapt_threshold(&image, thresh, lt, flags);
thresh = adapt_threshold(&image, thresh, lt, flags, UPDATE);
} else {
fprintf(stderr, "%s: error: crop command needs 4 arguments\n", PROG);
exit(99);
@@ -1068,6 +1083,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();
@@ -1117,6 +1133,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);