PHOTOS - Convert single or batch

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
Locked
xinu
Level 3
Level 3
Posts: 148
Joined: Fri Apr 24, 2015 1:39 am

PHOTOS - Convert single or batch

Post by xinu »

Hello Minters,

Maybe I should 've put this under 'Multimedia', but still,

hereby a full bash script I've written (and translated from my mother tongue) to convert a bunch of (jpg) photos at once.

See also my other script '0000_Fotos_Sort_to_Portrait_or_Landscape.sh'

I've named the script '0000_FFmpeg_Photo_Scripts_Resize_and_Sharpen_Batch_or_Single_New_Dir.sh' (starting with 0000 to make it land on top of the input dir)

The script uses ffmpeg.

Tweak to your personal desires (I've got another, seperate version for conversion within the same dir - not creating a new dir. Have tested this only with jpeg images).
Give the script convenient rights.
Reply if you see sth that could be done in a better way.

TIPS:

'unsharp=5:5:0.20:5:5:0.0 -q:v 5'

The explanation of this is in the ffmpeg documentation.
I would leave the '5:5' and the other '5:5' alone.
The sharpening/blurring tweaks are in the decimal numbers.
I've used 0.20 to slightly sharpen without overdoing it.
The quality of '-q:v 5' is still a good quality and it reduces the file size of pictures with almost half, without the human eye noticing a lot of difference.
'-q:v 2' would be the max quality.

I've taken a default image width of 1280. The height gets adapted to that with the '-1'.
In the case of vertical (portrait) pictures I set the width to 720 and usually let the height adapt to that by letting it be '-1'.
Smaller dimensions would be (Landscape) 640x360.
But, you can set the width and the height to anything you want.

Code: Select all

#!/bin/bash

echo -en '\e[8;14;80t' # Window Size

TITLE="FFMPEG - PHOTO(S) RESIZE SINGLE OR BATCH NEW DIR"
echo -en "\033]0;$TITLE\a" # Window Title

clear

echo "$TITLE"

echo

echo "Place this script on top of photos,"
echo "after having divided between landscape or portrait pictures."
echo "The converted photos are moved to a new dir."

echo

echo "SOURCE (single file or multiple with wildcard)?"

read -e -i "*.jpg" -p "" SOURCE

echo

echo "Desired Width (Default 1280px Landscape, 720px Portrait. Number only.)?"

read -e -i "1280" -p "" WIDTH

echo

echo "Desired Height (-1 = adaptive to width or specific e.g.: 720px Landscape)?"

read -e -i "-1" -p "" HEIGHT

echo

echo "Extension of destination file(s) (without dot)?"

read -e -i "jpg" -p "" DESTEXT

echo

echo "Name of new dir with converted file(s)?"

read -e -i "Resized_W${WIDTH}_0001" -p "" FOLDER

echo

# Codes

for filename in ./${SOURCE}; do ffmpeg -i "$filename" -vf scale=${WIDTH}:${HEIGHT},unsharp=5:5:0.20:5:5:0.0 -q:v 5 "${filename%.*}_W${WIDTH}.${DESTEXT}"; done

mkdir -p ./${FOLDER}

mv *_W${WIDTH}.${DESTEXT} ./${FOLDER}

<< 'UNSHARP FFMPEG DOCUMENTATION'
Sharpen or blur the input video.

It accepts the following parameters:

luma_msize_x, lx
Set the luma matrix horizontal size. It must be an odd integer between 3 and 23. The default value is 5.

luma_msize_y, ly
Set the luma matrix vertical size. It must be an odd integer between 3 and 23. The default value is 5.

luma_amount, la
Set the luma effect strength. It must be a floating point number, reasonable values lay between -1.5 and 1.5.

Negative values will blur the input video, while positive values will sharpen it, a value of zero will disable the effect.

Default value is 1.0.

chroma_msize_x, cx
Set the chroma matrix horizontal size. It must be an odd integer between 3 and 23. The default value is 5.

chroma_msize_y, cy
Set the chroma matrix vertical size. It must be an odd integer between 3 and 23. The default value is 5.

chroma_amount, ca
Set the chroma effect strength. It must be a floating point number, reasonable values lay between -1.5 and 1.5.

Negative values will blur the input video, while positive values will sharpen it, a value of zero will disable the effect.

Default value is 0.0.

All parameters are optional and default to the equivalent of the string ’5:5:1.0:5:5:0.0’.

UNSHARP FFMPEG DOCUMENTATION

# -q:v = set the quality of the (jpeg) output. Values to 2 to 31. The lower, the better quality, the higher file size.
# Good values, sharpen slightly and smaller file size: unsharp=5:5:0.20:5:5:0.0 -q:v 5

echo

echo "Enter = Reload Script"
echo "Ctrl+c of Close button = Close"

read

exec bash "$0" "$@" # Restart script from the beginning
Last edited by LockBot on Wed Dec 28, 2022 7:16 am, edited 4 times in total.
Reason: Topic automatically closed 6 months after creation. New replies are no longer allowed.
User avatar
Termy
Level 12
Level 12
Posts: 4248
Joined: Mon Sep 04, 2017 8:49 pm
Location: UK
Contact:

Re: PHOTOS - Convert single or batch

Post by Termy »

Some suggestions:
  • I'd remove the use of clear(1), as it unnecessarily blasts away some of the user's existing terminal output.
  • I'd remove the unnecessary stray echo calls, instead making use of the \n escape character.
  • I'd make the script more robust by checking the user's input having a value and being valid.
  • You have null -p (prompt) flags with the read builtin; I'd remove them, or use them as intended.
  • You have one-liner syntax in a script, which is unnecessary and greatly affects readability. (L52)
  • You've created a directory, but have no checks for whether it created it successfully.
  • You move a lot of files using mv(1), but you're not checking for them being files*.
  • You're handling files but have no permission-related checks.
If you can address those things, you'll vastly improve it. :)

The by-the-book formatting for L52, by the way, is:

Code: Select all

for filename in ./${SOURCE}
do
	ffmpeg -i "$filename" -vf scale=${WIDTH}:${HEIGHT},unsharp=5:5:0.20:5:5:0.0 -q:v 5 "${filename%.*}_W${WIDTH}.${DESTEXT}"
done
However, my approach would be:

Code: Select all

for filename in ./${SOURCE}; {
	ffmpeg -i "$filename" -vf scale=${WIDTH}:${HEIGHT},unsharp=5:5:0.20:5:5:0.0\
		-q:v 5 "${filename%.*}_W${WIDTH}.${DESTEXT}"
}
Now the lines aren't going far off the screen, and its much clearer. This might seem unimportant to you, but please trust me when I say that readability does matter, especially if you're going to be sharing your stuff, or hope to write and distribute full programs. In my early days of programming, I didn't care too much about readability or convention, as long as I knew what I was doing. Eventually, my code and mindset matured.

The use of the braces is a bashism, by the way; I prefer it because it's easier and quicker to type, and is akin to various other languages. When in Rome...

If you're curious, you could have a look at my Extra repository on my GitHub, in which you'll find many Bourne Shell and BASH programs I've written and maintained over the years. I'm told they're quite helpful in seeing how various tasks can be achieved.

* I'm assuming you are wanting to move just files, in which case, although it's not as efficient, I'd opt for a for loop.
I'm also Terminalforlife on GitHub.
xinu
Level 3
Level 3
Posts: 148
Joined: Fri Apr 24, 2015 1:39 am

Re: PHOTOS - Convert single or batch

Post by xinu »

Thanks for your good advise, Termy.

The script works, but could turn out better with your tips.
Locked

Return to “Scripts & Bash”