Render string in X11 bitmap font - linux

How do I render a string in an ancient X11 bitmap font? I mean something like
-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*
which I can find with xfontsel. I just need a command line tool etc. that displays a given string in that font. A similar TrueType font won't work, since it has to be pixel-perfect (I'm trying to get images of each letter to OCR an image in that font).

I'm not sure if there is a command line tool. But you can always roll your own with Xlib and C.
Somebody seems to have written a simple X11 C program that displays a string using Xlib. Changing a couple of lines and compiling with:
gcc -lX11 -o xrenderstring xrenderstring.c
.. should do it for you.
I've reproduced the entire program in this gist (in case it vanishes from the original source), modified to take two arguments: 1. fontname, 2. string to be rendered.
So you'd call it like (after compiling of course):
./xrenderstring "-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*" "Quick brown fox"

To just render characters in that font:
xfd -fn '-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*'
xfontsel -pattern '-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*'
To render a specific string:
xfontsel -pattern '-*-lucida-medium-r-normal-*-34-*-*-*-*-*-*-*' -sample 'The quick brown fox jumps the shark'

Found a hackish way. Add the following to ~/.Xdefaults:
xedit*editWindow*font: -*-lucida-medium-r-normal-*-36-*-*-*-*-*-*-*
and then run
$ xrdb -merge ~/.Xdefaults
$ xedit
Then I typed the string in, took a screenshot, and compared it in gimp.
(Turns out the X11 font was not quite the right one after all. My source used Lucida Sans 36 pt (ttf), but without antialiasing and probably wierd hinting.)

You can use ImageMagick.
Added benefits:
can render old-fashioned (fixed) or TTF or other fonts
can render to screen or to image file (PNG, whatever)
Simple
For short text
echo "The quick brown fox jumps over the lazy dog." \
| convert \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
TEXT:- -trim fox.png
To render to screen:
echo "The quick brown fox jumps over the lazy dog." \
| convert \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
TEXT:- -trim MIFF:- | display MIFF:-
Remove -trim to see that ImageMagick uses a canvas to draw.
More control
Canvas size. To avoid two-step computations, create a canvas larger than needed and trim it afterwards.
Control background and foreground colors.
Control PNG parameters (one bit per pixel)
convert -size 2000x20 xc:black \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
-fill white \
-draw "text 0,15 'The quick brown fox jumps over the lazy dog.'" \
-trim +dither -depth 1 fox.png
The resulting image below weighs 592 bytes:
To get independently framed characters (for later composition)
You could put only one character in line above, but applying to several characters independently would cause the resulting images to no longer have a same size nor same common baseline.
for CHAR in H e l o ' ' W r d
do
convert -size 9x13 xc:black \
-font '-*-fixed-*-*-*-*-18-*-*-*-*-*-iso8859-*' \
-fill white -stroke none \
-draw "text 0,10 '${CHAR}'" \
+dither -depth 2 fixed_char_${CHAR}.png
done
The command below produces a PNG showing that individually framed images keep their common alignment:
montage -mode concatenate -tile x1 fixed_char_H.png fixed_char_e.png \
fixed_char_l.png fixed_char_l.png fixed_char_o.png fixed_char_\ .png \
fixed_char_W.png fixed_char_o.png fixed_char_r.png fixed_char_l.png \
fixed_char_d.png helloworld.png

Related

Can't fit text to image with ImageMagick

I need to fit my text to image. My image have different sizes so i can't set constant pointsize.
My command looks something like this
convert
-fill white
-font Winter Calligraphy
-size `${options.width}x${options.height}`
label: KJHGFD
test.gif
on output you can see cropped part on top of picture.
Output:
I have problem only with this fonts, other fonts works great.
I tried to add white border on top. Unfortunately, this only moved the damaged text to bottom.
I can't change area size.
Text must fill as much space as possible.
I need to use Winter Calligraphy font
Here is a slightly kludgy way of getting the result you want. Here are the steps:
First, use caption: to get ImageMagick to tell you the pointsize it would use to fill your text box and extract that info
Create a canvas twice as wide and twice as tall as the one you really want and draw your text in the middle of that - it is bound to fit!
Now trim away the extraneous background around the text so you have the absolute minimum bounding box to contain the text
Resize the result to your desired size.
#!/bin/bash
# Width, height and text
w=600
h=150
text="KJHGFD"
# Get pointsize ImageMagick thinks is good
pointsize=$(convert -gravity center -background black -fill white -size ${w}x${h} \
-font "Winter Calligraphy.ttf" caption:"$text" -format "%[caption:pointsize]" info:)
echo ImageMagick likes pointsize: $pointsize
# So draw text in that size on larger canvas, trim to bounds of letters and resize to desired size
wb=$((w*2))
hb=$((h*2))
convert -gravity center -fill white -size ${wb}x${hb} xc:black \
-font "Winter Calligraphy.ttf" -pointsize $pointsize -annotate 0 "$text" \
-trim +repage -resize ${w}x${h}\! result.png
This works for me in ImageMagick 6.9.10.97 Q16 Mac OSX. I have added -background white -fill black -gravity center to your command.
convert -background white -fill black -font "/library/fonts/Winter Calligraphy.ttf" -size 569x196 -gravity center label:KJHGFD test.gif

Using ImageMagick to remove all color except black in an image?

The situation is : I have many images of documents from scanning. I want to keep the document's main content - which is printed in color black (a small range of colors around #000000). But, you know, the documents are always full of colors : stamp, background, decorations, logos...etc.
I just want to keep the TEXTS ONLY which were printed in the color black.
I've tried with ImageMagick and this command so far:
convert X.png -matte (+clone -fuzz 20% -transparent "#000000") -compose DstOut -composite X1.png
But the result was not as expected , the text was very damaged that I cannot read.
Someone suggested me to increase the fuzz to 70%:
convert X.png -matte (+clone -fuzz 70% -transparent "#000000") -compose DstOut -composite X1.png
Then the text appeared to be more readable, but the other colors kept remaining too.
Can you please show me a better solution for my situation? Every suggestion would be highly appreciated!
To match all colors except black you can use +opaque "#000000".
In order to include a little range around #000000 you can try different percentages with the fuzz operator:
convert input.png -fill white -fuzz 10% +opaque "#000000" result.png
Tested with ImageMagick 6.6.0-1 on Windows
I stumbled upon this question while looking for an answer to this question. I found a couple imagemagick forum posts that helped. Here is what I came up with:
convert input.gif -matte \( +clone -fuzz 1 -transparent black \) -compose DstOut -composite ~/Desktop/output.png
Forum post: ImageMagick: Removing all but one color
You should try the level command:
convert test.png -level 25%,75% test_level.png

ImageMagick - quoted numbers as convert label argument causes the command to fail

my shell hangs on this command:
/usr/local/bin/convert -size 298x71 -background black -fill white -stroke none -gravity center -trim -interline-spacing 0 -font /home/amazingw/public_html/live/fonts/Phillies.ttf label:'150' png:-
The shell just sits there until i press ctrl+c. If I add any letter to the label: argument the command runs fine and I get output.
The font is there but it is missing the number characters in the definition.
Could that cause my command to fail?
This seems like an issue related to input at the console, I am assuming you are using Bash.
If this is the case, Bash is trying to interpret the quotes and is waiting for other input.
after reviewing the imagemagick website for "label:"
Label - Simple Text Label
Basic Labels
Creating a font image using a "label:" image,
is the more typical way of drawing a font
quickly in ImageMagick...
It goes on and gives many examples...
convert -background lightblue -fill blue \
-font Candice -pointsize 72 label:Anthony \
label.gif
None of the examples show single quotes.
I would assume between Bash and ImageMagick's convert program, there is some error on interpretation of input from the console.
I would suggest trying your same command without quotes
/usr/local/bin/convert -size 298x71 -background black -fill white -stroke none -gravity center -trim -interline-spacing 0 -font /home/amazingw/public_html/live/fonts/Phillies.ttf label:150 png:-
I would also take a quick look at the Bash manual about single quotes too.
I was able to test using a modified version of the font which contained the digits. Command went smoothly and an output image was returned. This pretty much narrows it down to an ImageMagick problem with handling labels. Looks like if the label is made out only of characters which are missing in the font (the resulting output image would be empty) - in that case ImageMagick hangs until ctrl+c is pressed - especially problematic as I'm running this from php's proc_open.

Insert a text chunk into a png image

I'm looking for a simple command-line tool (on Linux) to insert a text chunk (e.g. copyright) into a png file, resulting in a new png file:
> png-insert-text-chunk "here's my text chunk" < in.png > out.png
Note: by "insert a text chunk", I do not mean "draw some text on the image". I mean: insert the text into the png file as a chunk, in the technical sense. This can be used, for example, to insert a copyright message that isn't displayed on the actual image.
Use ImageMagick's convert and the -set option:
convert IN.png \
-set 'Copyright' 'CC-BY-SA 4.0' \
-set 'Title' 'A wonderful day' \
-set comment 'Photo taken while running' \
OUT.png
The -set option is used to set metadata elements. In the case of PNG these often go into tEXt chunks.
I have searched around for utilities to do this, and not yet found anything that really matches what I want to do. So I decided to build my own, which it turns out is not too hard. The utility png-text-dump displays all text chunks in a PNG image. It depends only on libpng. The utility png-text-append inserts text chunks into a PNG image. It depends only on the standard C library - I had initially tried to implement this using libpng, but actually found it easier to work from scratch using only the PNG specification.
Note: This answer was a response to the original revision of the question where it was not clear if the text had to be written on the image or if the text had to be embedded within the image binary file as metadata. This answer assumed the former. However the question was edited to clarify that it meant the latter. This answer is left intact, in case someone is looking for a solution to the former.
convert -draw "text 20,20 'hello, world'" input.png output.png
The 20,20 in the above example is the co-ordinate where I want to place the text.
You need to use the imagemagick package to get this command.
On Ubuntu or Debian, it can be installed with the command: apt-get install imagemagick.
Here is a slightly more elaborate usage of the command:
convert -font Helvetica -pointsize 20 -draw "text 20,20 'hello, world'" input.png output.png
This can be implemented with python pypng module. The python3 example code is below:
import png
TEXT_CHUNK_FLAG = b'tEXt'
def generate_chunk_tuple(type_flag, content):
return tuple([type_flag, content])
def generate_text_chunk_tuple(str_info):
type_flag = TEXT_CHUNK_FLAG
return generate_chunk_tuple(type_flag, bytes(str_info, 'utf-8'))
def insert_text_chunk(target, text, index=1):
if index < 0:
raise Exception('The index value {} less than 0!'.format(index))
reader = png.Reader(filename=target)
chunks = reader.chunks()
chunk_list = list(chunks)
print(chunk_list[0])
print(chunk_list[1])
print(chunk_list[2])
chunk_item = generate_text_chunk_tuple(text)
chunk_list.insert(index, chunk_item)
with open(target, 'wb') as dst_file:
png.write_chunks(dst_file, chunk_list)
def _insert_text_chunk_to_png_test():
src = r'E:\temp\png\register_05.png'
insert_text_chunk(src, 'just for test!')
if __name__ == '__main__':
_insert_text_chunk_to_png_test()
I believe that pngcrush has this ability: http://pwet.fr/man/linux/commandes/pngcrush
Adding to the comment made by #susam-pal, to change color use the option
-fill color
This option accepts a color name, a hex color, or a numerical RGB, RGBA, HSL, HSLA, CMYK, or CMYKA specification. See Color Names for a description of how to properly specify the color argument.
Enclose the color specification in quotation marks to prevent the "#" or the parentheses from being interpreted by your shell.
For example,
-fill blue
-fill "#ddddff"
-fill "rgb(255,255,255)"
Obtained from link

Automate conversion of text to PNG (or another file format with transparency)?

I need to take a list of words and create a PNG file of each, with a transparent background.
I’d like my script to allow for adjustable opacity of the foreground, but I can probably also do it after the fact when the images get imported into Matlab.
I imagine this is doable with ImageMagick and have installed that on my Mac. If someone can give me the one line I’d need to turn a word into a PNG (the word can be the filename too) in Perl or Python, I can probably figure out the rest of the scripting.
I found this to be applicable to your question:
convert -size 560x85 xc:transparent -font Palatino-Bold -pointsize 72 -fill black -draw "text 20,55 'Linux and Life'" linuxandlife.png
Output:
size 560x85 : the size (width x height) of the image
xc:transparent : xc means X window color, use "transparent" to get a transparent background
fond Palatino-Bold : the font of the text ( type "identify -list font" in the terminal to know all the supported fonts)
pointsize 72 : the size of the text
fill black : the color of the text ( check this link to know the names of the supported colors)
draw "text 20,55 'Linux and Life'" : the position of the text and the text itself
linuxandlife.png : the output image
Matplotlib (better known as pylab) would work great for this. Assuming ImageMagick is installed this script should work. (tested on Ubuntu 9.10)
import pylab as py, os
W = ['cat','dog','mouse']
for word in W:
py.clf()
ax = py.axes(alpha=1.0)
py.text(0,.5,word)
py.axis('off')
py.savefig("%s.png"%word)
os.system('convert -trim %s.png %s.png' % (word,word))
This creates three files on my system dog.png, cat.png and mouse.png all cropped with a transparent background.

Resources