Caption images from multiple txt files

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
Nat
Posts: 6
Joined: 2020-02-08T17:13:18-07:00
Authentication code: 1152

Caption images from multiple txt files

Post by Nat »

- ImageMagick Version: 7.0.9-8 Q16 x86_64 2019-12-21
- Mac OS / Unix

Hi! I’m new to ImageMagick and scripting / coding.

I’m interested in making a series of 800x800px images that read captions from txt files to form new .png images.

Each txt file is similar to the following and is stored in the directory: authors/text/ For example, mark_twain.txt looks like:

Mark Twain
The Adventures of Tom Sawyer
1876
Huckleberry Finn
USA

The background is: background_800x800.png

After creating the first image, I am then adding a Category with a gravity of Northwest (that is positioned above and to the Northwest corner) from the mark_twain.txt file information, which is centered in the image.

Here’s what I am currently doing to create a single image:

First I am adding the author etc. info from the txt file:

magick background_800x800.png \( -size 700x600 -background none -fill red -font courier -pointsize 58 -gravity center caption:"$(cat ./mark_twain.txt)" \) -gravity center -geometry +0+50 -compose over -composite mark_twain.png

Then, to add a category (fiction) I’m running the following:

magick mark_twain.png \( -background none -size 300 -font courier -pointsize 38 -fill black caption:"$(cat ./category_fiction.txt)" \) -gravity northwest -geometry +80+120 -compose over -composite mark_twain_full.png

How do I change this to batch caption for 50 files? (Let’s assume that all are Fiction)

Is there a best practice for what I’m trying to accomplish that I am missing? I’m new to this and I don’t understand how to apply this to create images from multiple .txt files. Is there a variable for the input filenames and output files?

I’ve been looking at examples of other scripts, but haven’t quite figured it out.

Thanks for your help!

Nat

User avatar
fmw42
Posts: 26061
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Caption images from multiple txt files

Post by fmw42 »

You will have to write a bash script "for" loop over each input text file using your command if you know the placements you want. Those can be set in another text file. Alternately, you can loop over each input text file, create the caption image and then -append (or -smush) them vertically to form one file. The -smush command allows you to put spacing between the created files.

Post 3 sets of text or the text files (to some free hosting service and put the urls here) and I will try to show you how to loop and use -smush.

But how will 50 of these fit into one 800x800 px image? Do you know what dimensions you want to use for the captions and the spacing between text sections?

Nat
Posts: 6
Joined: 2020-02-08T17:13:18-07:00
Authentication code: 1152

Re: Caption images from multiple txt files

Post by Nat »

Hi Fred,

Thanks for your quick reply. I'm interested in creating 50 images in total, one image for each author. So there will be a Mark Twain image, a J.D. Salinger image etc. Each image will be 800x800. Sorry for the confusion!

User avatar
fmw42
Posts: 26061
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Caption images from multiple txt files

Post by fmw42 »

Here I have duplicated your mark_twain text 3 times as files. And created a one line text file for your categories_fiction file. I then create an 800x800 white background image. You can replace that with any other file you want of the same size. I have concatenated your two commands into one command line to avoid writing an intermediate file. I made a list of the text files to process. It could be replaced with a file containing a list of files or potentially using a wild card, if the file names are consistent.

Try this with just one or two or three files first to see if it works.

Code: Select all

magick -size 800x800 xc:white background_800x800.png
list="mark_twain1.txt mark_twain2.txt mark_twain2.txt"
i=1
for file in $list; do
echo $file
magick background_800x800.png -colorspace sRGB \
-size 700x600 -background none -fill red -font courier -pointsize 58 -gravity center caption:"@mark_twain1.txt" \
-gravity center -compose over -composite \
-size 300x -background none -font courier -pointsize 38 -fill black caption:"@category_fiction.txt" \
-gravity northwest -geometry +80+120 -compose over -composite \
mark_twain_full_$i.png
i=$((i+1))
done
The @filename.txt is Imagemagick way of reading a text file. But it may need you to change your policy.xml file to give it permission to do so.

Let me know what happens.

Nat
Posts: 6
Joined: 2020-02-08T17:13:18-07:00
Authentication code: 1152

Re: Caption images from multiple txt files

Post by Nat »

Hi Fred,

Thanks for taking the time to help me with this, it’s much appreciated!

While trying to run the loop, I’ve been getting a syntax error with the $list in line 4.

File "<ipython-input-50-23f9ae78a950>", line 4
for file in $list; do
^
SyntaxError: invalid syntax

That could be from some beginner mistake on my part. I’m currently trying to determine why I’m getting that error in executing the loop. I don’t believe it’s related to policy.xml, as I’ve been able to read @files.txt and use them to create sample images.

I’ll see if I can discover what the issue is and update you soon.

Thanks again!

Nat

Nat
Posts: 6
Joined: 2020-02-08T17:13:18-07:00
Authentication code: 1152

Re: Caption images from multiple txt files

Post by Nat »

I was running it in a Jupyter Notebook, so that might be the problem, but I've run For loops inside them before without an issue.

But I did notice the error code just now, and perhaps it's looking for Python, which would cause it to be invalid syntax.

Usually if you start a line in Jupyter Notebook with a ! it runs in bash without an issue.

File "<ipython-input-50-23f9ae78a950>", line 4
for file in $list; do
^
SyntaxError: invalid syntax

I'll keep testing it out and see if I can figure out what's causing the issue on my side. Thanks!

User avatar
fmw42
Posts: 26061
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Caption images from multiple txt files

Post by fmw42 »

Sorry, I do not know anything about Jupyter. My code needs to be run in a bash shell.

Nat
Posts: 6
Joined: 2020-02-08T17:13:18-07:00
Authentication code: 1152

Re: Caption images from multiple txt files

Post by Nat »

Hi Fred,

Thanks! The script works well in bash shell, the two things I still have a question about are:

What should I change the ‘caption’ command to in order to read text from all three files? Currently I believe it’s only set to only read a single file:

caption:"@mark_twain1.txt" \

I’ve tried caption:”@mark_twain.txt @shelley.txt @sallinger.txt” but that didn’t work for me.

How do I pluralize this to read captions from the three files? @mark_twain.txt @shelley.txt @salinger.txt

One idea I had, and it might be totally wrong... the code below got me the desired output in Bash, but I don’t know how to direct this info as an input to the ‘caption’ command to create three separate images.

myvar=$( cd ./texts | cat mark_twain.txt salinger.txt shelley.txt )

I’ve been playing around with hundreds of different combinations today, but I still haven’t been able to solve it yet.

You also mentioned that I could create a file that specifies the .txt files to be read by the caption command? How does that work?

Assuming the file names to be captioned are:
mark_twain.txt salinger.txt king.txt

How would I go about creating such a file?

Any tips you have would be useful!

The problem with being new at this is that I don’t know the terms to search for.

Thanks!

Nat

User avatar
fmw42
Posts: 26061
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Caption images from multiple txt files

Post by fmw42 »

Caption: can only take 1 file at a time. But you can put 3 captions with corresponding composites in the same command with different placements. Or you can concatenate the 3 files with some Unix tool. But I thought you said before that you only want one file per image for 50 files. The script I provided allows you to created 3 or more files from the list of files.

User avatar
fmw42
Posts: 26061
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Caption images from multiple txt files

Post by fmw42 »

I made a mistake in the previous code and it restricted it to a fixed file. Here is the proper code.

Code: Select all

magick -size 800x800 xc:white background_800x800.png
list="mark_twain1.txt mark_twain2.txt mark_twain2.txt"
i=1
for file in $list; do
echo $file
magick background_800x800.png -colorspace sRGB \
-size 700x600 -background none -fill red -font courier -pointsize 58 -gravity center caption:"@$file" \
-gravity center -compose over -composite \
-size 300x -background none -font courier -pointsize 38 -fill black caption:"@category_fiction.txt" \
-gravity northwest -geometry +80+120 -compose over -composite \
mark_twain_full_$i.png
i=$((i+1))
done

If you want to read the list from a file, then look up "while read" unix command. It reads a line of text from a file. The file is just a simple text file with the names of your files listed one row at a time. In this case it is just:

Code: Select all

mark_twain1.txt
mark_twain2.txt
mark_twain2.txt
Here is the code:

Code: Select all

magick -size 800x800 xc:white background_800x800.png
list="mark_twain1.txt mark_twain2.txt mark_twain2.txt"
i=1
while read line; do
echo $line
magick background_800x800.png -colorspace sRGB \
-size 700x600 -background none -fill red -font courier -pointsize 58 -gravity center caption:"@$line" \
-gravity center -compose over -composite \
-size 300x -background none -font courier -pointsize 38 -fill black caption:"@category_fiction.txt" \
-gravity northwest -geometry +80+120 -compose over -composite \
mark_twain_full_$i.png
i=$((i+1))
done < <( cat file_list.txt )

User avatar
fmw42
Posts: 26061
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Caption images from multiple txt files

Post by fmw42 »

If you want 3 text files concatenated, you can use the unix tool cat, then pipe the results to magick where you use @- for the caption:

Code: Select all

magick -size 800x800 xc:white background_800x800.png

cat mark_twain1.txt mark_twain2.txt mark_twain2.txt | magick background_800x800.png -colorspace sRGB \
-size 700x600 -background none -fill red -font courier -pointsize 28 -gravity center caption:"@-" \
-gravity center -compose over -composite \
-size 300x -background none -font courier -pointsize 38 -fill black caption:"@category_fiction.txt" \
-gravity northwest -geometry +80+120 -compose over -composite \
mark_twain_full_3files.png
But you need to put the spacing as empty lines in the text files.

Nat
Posts: 6
Joined: 2020-02-08T17:13:18-07:00
Authentication code: 1152

Re: Caption images from multiple txt files

Post by Nat »

Awesome! Thanks Fred! Examples 1 and 2 were exactly what I was struggling to accomplish.
I'll look into the 'while read' Unix command. Thanks for the tip!

I appreciate your help with this problem and hope I can give back to the community at some point!

Thanks again!

Nat

Post Reply