Page 1 of 1

Labelling in either black or white

Posted: 2011-05-21T14:29:05-07:00
by whugemann
I am trying to label photographs with either white or black letters, depending on the mean brightness of the local background, in order to acchieve the maximum contrast. I already read Anthony's remarks on labelling and reached at the following DOS beatch file:

Code: Select all

SETLOCAL ENABLEDELAYEDEXPANSION
SET Option=-pointsize 100 -background "#00000000" -fill 
convert %Option% white label:"Test" label.miff

FOR /F %%i in ('identify -format %%wx%%h Label.miff') DO ^
convert DSCN9046_r.JPG -gravity northeast -crop %%i+0+0 test.miff

FOR /F %%i IN ('Identify -format "%%[fx:mean]" test.miff') DO ^
IF %%i LEQ 0.5 (
SET Color=white
) Else (
SET Color=black
)

convert %option% !color! label:"Test" DSCN9046_r.JPG -reverse -compose over  -gravity northeast -geometry +0+0 -composite DSCN9046_c.jpg
I hope this is somehow legible to non-Windows users. What I basically do is:
1) Generate an image with the label in white letters
2) Identify its size
3) Cut the according piece from the image that I want to label
4) Identify its mean value (fx gives values 0 -- 1)
5) If this value is less than 0.5 --> white letters, otherwise black letters
6) Do the actual labelling with the correct letter color.

Although the code works, I wonder if there is a more elegant solution to the problem, without creating so many temporal files.

One problem was that -gravity isn't available for Identify. And there seems to be no -identify option for Convert, such that I could try to create an interim result and use it in the same command line. Piping in Windows is limited to simple string values.

Re: Labelling in either black or white

Posted: 2011-05-21T16:23:52-07:00
by fmw42
Wolfgang

In my autocaption script (and somewhat similar in my autolabel script), I do something similar. But I scale the appropriate section of the image to 1x1 pixel (average it), convert to gray, then get the (percent) gray level value in range 0 to 100. Then test that to determine whether to color with white or black. Basically the following although I have expressed it a bit more efficiently here than what I used in my script. If you can convert this for windows, it might save you one step.

gray=`convert $tmpA2[${sizep}x${sizep}+${xxm}+${yym}] -scale 1x1\! -colorspace gray -format "%[fx:round(100*s.r)]" info:`
[ $gray -lt 50 ] && color="white" || color="black"

In unix, this probably could be done in one complex step as (though untested):

[ `convert $tmpA2[${sizep}x${sizep}+${xxm}+${yym}] -scale 1x1\! -colorspace gray -format "%[fx:round(100*s.r)]" info:` -lt 50 ] && color="white" || color="black"

Fred

Re: Labelling in either black or white

Posted: 2011-05-21T22:29:47-07:00
by anthony
I would however not only color the text the opposite of the general background, but also surround the text with a slight darkening or lightening (opposite color of the text) to ensure the text remains visible.

See Annotataing Images
http://www.imagemagick.org/Usage/annotating/

You could overlay that lightening or darking using some type of lighten or darken overlay operator, so that it is only added as nessary
http://www.imagemagick.org/Usage/compose/#lighten

Basically you can do a lot, and typically it only depends on how much effort and how far you want to take it.

Re: Labelling in either black or white

Posted: 2011-05-23T00:57:50-07:00
by whugemann
Thanks to your hints I arrived at a much shorter solution:

Code: Select all

SETLOCAL ENABLEDELAYEDEXPANSION
SET image=DSCN9046.jpg
SET gravity=-gravity Northeast
SET Option=-pointsize 100 -background "#00000000" -fill 

FOR /F %%i IN ('convert %Option% white label:"Test" -format %%wx%%h info:') DO ^
FOR /F %%j IN ('convert %image% %gravity% -crop %%i+0+0 -format "%%[fx:(mean<0.5)?1:0]" info:') DO ^
convert %Option% rgb(%%j00%%,%%j00%%,%%j00%%) label:"Test" %image% -reverse -compose over %gravity% -geometry +0+0 -composite c_%image%
The decisive hint was that I can substitute Identify by Convert -format ... info:. This allows me to use options which are only available for Convert, such as -gravity.
Another hint was the usage of the ternary conditional expression, which I now use to flip between white and black in the second Convert command. The value of either 1 or 0 is stored in %j and reused to generate the rgb percentages in the final Convert statement.

The statement
FOR /F %%x in ('statement') DO ...
is DOS's crude way to reuse the result of a command line ...