mirror of
https://github.com/tonydamage/nux-env.git
synced 2025-12-11 13:24:28 +01:00
341 lines
9.6 KiB
Text
Executable file
341 lines
9.6 KiB
Text
Executable file
#!/usr/bin/env nuxsh
|
|
|
|
nux.use nux/fs
|
|
|
|
@prefix fs nux.fs.
|
|
@prefix check nux.check.
|
|
|
|
|
|
type ffmpeg > /dev/null 2>&1 && FFMPEG_OR_LIBAV=ffmpeg
|
|
type avconv > /dev/null 2>&1 && FFMPEG_OR_LIBAV=avconv
|
|
type gm > /dev/null 2>&1 && NUX_MAGICK=gm
|
|
|
|
QUALITY=${QUALITY:=95}
|
|
DUPLICATE_THRESHOLD=${DUPLICATE_THRESHOLD:=90%}
|
|
SKIP_CHECK=no_skip
|
|
nux.log debug "FFMPEG: $FFMPEG_OR_LIBAV Magick: $NUX_MAGICK"
|
|
|
|
## Performs operations on media such as images or videos.
|
|
## Use env **QUALITY** to specify compression quality.
|
|
##
|
|
## # Available tasks:
|
|
@command video.change.container {
|
|
CONTAINER=$1;
|
|
shift;
|
|
echo "Using $FFMPEG_OR_LIBAV for conversion."
|
|
for video in "$@"; do
|
|
echo "Starting processing Video: $video";
|
|
$FFMPEG_OR_LIBAV -i "$video" -vcodec copy -acodec copy "${video}.$CONTAINER"
|
|
echo "Processing done.";
|
|
done
|
|
}
|
|
|
|
@command function :nikon-mp4 {
|
|
task.video.change.container mp4 "$@"
|
|
}
|
|
|
|
|
|
@command keep-path task {
|
|
|
|
}
|
|
|
|
## remove-orig:: <task> <task arguments...>
|
|
## Runs specified task, but remove original images if applicable.
|
|
## This keyword is applicable for *downscale*, *to*
|
|
@command remove-orig task {
|
|
nuxr.run "$task" "$@"
|
|
}
|
|
|
|
## no-overwrite:: <task> <task arguments...>
|
|
## Runs specified task, but remove original images if applicable.
|
|
## This keyword is applicable for *downscale*, *to*
|
|
@command no-overwrite task {
|
|
SKIP_CHECK=nux.fs.exists
|
|
nuxr.run "$task" "$@"
|
|
}
|
|
|
|
@command preserve task {
|
|
PRESERVE=true
|
|
nuxr.run "$task" "$@"
|
|
}
|
|
|
|
@command inplace task {
|
|
NUX_INPLACE=true
|
|
nuxr.run "$task" "$@"
|
|
}
|
|
|
|
@command target-dir dir task {
|
|
NUX_TARGET_DIR="$dir"
|
|
nuxr.run "$task" "$@"
|
|
}
|
|
|
|
## downscale:: <target> <size> <image...>
|
|
## Creates downscaled copy of image in *target* directory.
|
|
## Image is downsampled to fit in *size*. Smaller images are not upscaled.
|
|
@command downscale TARGET SIZE {
|
|
local i=0;
|
|
local count="$#";
|
|
mkdir -p $TARGET;
|
|
for image in "$@"; do
|
|
let "i=i+1"
|
|
name="$(basename "$image")";
|
|
target_file="$TARGET/$name";
|
|
if [ -n "$PRESERVE" ]; then
|
|
target_dir="${TARGET}/$(dirname "$image")";
|
|
mkdir -p "$target_dir";
|
|
target_file="${target_dir}/$name";
|
|
fi
|
|
if $SKIP_CHECK "$target_file" ; then
|
|
nux.log debug "$target_file" "($i/$count) Skipping"
|
|
else
|
|
fs:info "$target_file" "($i/$count) Downsampling from $image"
|
|
$NUX_MAGICK convert "$image" \
|
|
-filter Lanczos -sampling-factor 1x1 \
|
|
-resize "${SIZE}x${SIZE}>" \
|
|
-quality $QUALITY \
|
|
"$target_file"
|
|
fi
|
|
done
|
|
}
|
|
|
|
## to:: <**jpg|png**> <image...>
|
|
## Convert image to specified format.
|
|
@command to target {
|
|
if ! nux.check.function "media.to.$target" ; then
|
|
echo Target type "$target" is not supported.
|
|
return -1
|
|
fi
|
|
for file in "$@"; do
|
|
target_dir=$(dirname "$file");
|
|
target_file=$(basename "$file" | sed -re 's/\.[a-z0-9_]+$//g' -e "s/\$/.$target/g" );
|
|
target_full="$target_dir/$target_file";
|
|
media.to.$target "$file" "$target_full"
|
|
echo $file $target_file
|
|
done
|
|
}
|
|
|
|
## datetime-name:: <image...>
|
|
## Normalizes name to format `yyyymmdd_hhmmss.suffix`
|
|
###
|
|
### Useful for:
|
|
### - generating RGBD Images for *holograms* - *left is color* space, *right is depth*
|
|
### - joining Instagram photos in slideshow, where photo is splitted in middle
|
|
@command datetime-name {
|
|
for file in "$@"; do
|
|
date=$($NUX_MAGICK identify -format "%[EXIF:DateTimeOriginal]" "$file" 2> /dev/null)
|
|
nux.log debug $file date is "'$date'"
|
|
if [ "(" -n "$date" ")" -a "(" "$date" != "unknown" ")" ]; then
|
|
target_dir=$(dirname "$file");
|
|
target_file=${date//:/};
|
|
target_file=${target_file/ /_};
|
|
target_suffix=${file##*.}
|
|
target_suffix=${target_suffix,,}
|
|
target_full="$target_dir/$target_file.$target_suffix";
|
|
fs:info "$file" Moving to: $target_full
|
|
fs:stage mv "$file" "$target_full"
|
|
else
|
|
fs:warning "$file" Can not identify date from EXIF
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
## side-by-side:: <left> <right> <output>
|
|
## Joins two images horizontal (assuming they have same size).
|
|
###
|
|
### Useful for:
|
|
### - generating RGBD Images for *holograms* - *left is color* space, *right is depth*
|
|
### - joining Instagram photos in slideshow, where photo is splitted in middle
|
|
@command side-by-side left right output {
|
|
$NUX_MAGICK montage -mode concatenate "$left" "$right" -geometry +0+0 -quality $QUALITY "$output"
|
|
nux.fs.info "$output" "Created"
|
|
}
|
|
|
|
@command split-horizontally image {
|
|
suffix=${image##*.}
|
|
basename=${image%.*}
|
|
$NUX_MAGICK convert "$image" -gravity east -chop 50%x0% "$basename.1.$suffix"
|
|
$NUX_MAGICK convert "$image" -gravity west -chop 50%x0% "$basename.2.$suffix"
|
|
}
|
|
|
|
@command split-vertically image {
|
|
suffix=${image##*.}
|
|
basename=${image%.*}
|
|
$NUX_MAGICK convert "$image" -gravity north -chop 0%x50% "$basename.1.$suffix"
|
|
$NUX_MAGICK convert "$image" -gravity south -chop 0%x50% "$basename.2.$suffix"
|
|
}
|
|
|
|
|
|
@command crop-to-aspect aspect gravity {
|
|
aspect_suffix=${aspect/:/_}
|
|
for image in "$@"; do
|
|
target="$(target.from "$image" "$aspect_suffix")";
|
|
#nux.fs.info "$image": Target image: "$target"
|
|
convert "$image" -gravity "$gravity" -crop "$aspect" "$target"
|
|
nux.fs.info "$target" "Image cropped to aspect ratio: $aspect"
|
|
done;
|
|
}
|
|
|
|
@command expand aspect gravity color {
|
|
aspect_suffix=${aspect/:/_}
|
|
for image in "$@"; do
|
|
target="$(target.from "$image" "$aspect_suffix")";
|
|
#nux.fs.info "$image": Target image: "$target"
|
|
gm convert $image -background $color -gravity $gravity -extent $aspect $target
|
|
nux.fs.info "$target" "Image cropped to aspect ratio: $aspect"
|
|
done;
|
|
}
|
|
|
|
|
|
|
|
|
|
## list-smaller:: <size> <image...>
|
|
## Lists images smaller than **size**.
|
|
@command list-smaller size {
|
|
$NUX_MAGICK identify -format "%f;%w;%h\n" "$@" | while IFS=";" read file w h ; do
|
|
if [ -z "$file" ]; then
|
|
continue;
|
|
fi
|
|
if [ $w -gt $size ] && [ $h -gt $size ]; then
|
|
continue;
|
|
fi
|
|
echo "$file $w $h"
|
|
done
|
|
}
|
|
|
|
@command list-different size {
|
|
$NUX_MAGICK identify -format "%f;%w;%h\n" "$@" | while IFS=";" read file w h ; do
|
|
if [ -z "$file" ]; then
|
|
continue;
|
|
fi
|
|
if [ $w -eq $size ] && [ $h -eq $size ]; then
|
|
continue;
|
|
fi
|
|
echo "$file $w $h"
|
|
done
|
|
}
|
|
|
|
## duplicates:: <image...>
|
|
## Analyse images for duplicates and display duplicate groups using feh.
|
|
## When image is displayed following actions are available:
|
|
## 0:: Keep file
|
|
## 1:: Move to folder with name of first image
|
|
## 2:: Replace with symlink to first image
|
|
## 3:: Remove file
|
|
###
|
|
### Environment variables:
|
|
### DUPLICATE_THRESHOLD:: Sets similarity treshold when images are
|
|
### considered similar. Default value is *90%*
|
|
###
|
|
@command duplicates {
|
|
nux.require findimagedupes
|
|
nux.require feh
|
|
findimagedupes -t $DUPLICATE_THRESHOLD "$@" | while read duplicate_set; do
|
|
largest=$(img.largest $duplicate_set)
|
|
set_name=${largest%.*}
|
|
nux.fs.info $largest Set name: $set_name
|
|
feh_files="";
|
|
for file in $duplicate_set; do
|
|
file=$(nux.fs.path.relative.pwd "$file");
|
|
#nux.fs.info $largest Possible duplicate $file
|
|
feh_files="$feh_files $file";
|
|
done
|
|
feh \
|
|
--zoom max \
|
|
--scale-down \
|
|
-G \
|
|
--action '[keep]echo %F: Keeping file.' \
|
|
--action1 "[move]echo %F: Moving to $set_name ; mkdir -p $set_name ; mv -t $set_name %F ;" \
|
|
--action2 "[symlink]echo %F: Replacing with symlink to $largest ; ln -sf $largest %F ;" \
|
|
--action3 "[delete] echo %F Removing file; rm -f %F;" \
|
|
--info 'echo %n: %wx%h' \
|
|
--draw-tinted $feh_files
|
|
done
|
|
}
|
|
|
|
## feh:: <image...>
|
|
## Displays images using feh.
|
|
## When image is displayed following actions are available:
|
|
## 0:: Next file
|
|
## 1:: -
|
|
## 2:: -
|
|
## 3:: Remove file
|
|
@command feh {
|
|
feh \
|
|
--zoom max \
|
|
--scale-down \
|
|
-G \
|
|
--action '[keep]echo %F: Keeping file.' \
|
|
--action3 "[delete] echo %F Removing file; rm -f %F;" \
|
|
--info 'echo %n: %wx%h' \
|
|
--draw-tinted "$@"
|
|
}
|
|
|
|
|
|
|
|
function img.largest {
|
|
## FIXME: Identify largest image
|
|
nux.fs.path.relative.pwd "$1";
|
|
}
|
|
|
|
function media.to.jpg {
|
|
$NUX_MAGICK convert "$1" -quality $QUALITY -auto-orient "$2"
|
|
}
|
|
|
|
function media.to.png {
|
|
$NUX_MAGICK convert "$1" -quality $QUALITY -auto-orient "$2"
|
|
}
|
|
|
|
function no_skip {
|
|
return 1;
|
|
}
|
|
|
|
function target.from image qualifier extension {
|
|
if [ -n "$NUX_INPLACE" ]; then
|
|
nux.log trace "Inplace edit: $image"
|
|
echo "$image"
|
|
else
|
|
orig_extension="${image##*.}"
|
|
basename="${image%.*}"
|
|
#if [-n "$NUX_TARGET_DIR" ];
|
|
#target_dir="$NUX_TARGET_DIR"
|
|
|
|
target="$basename"
|
|
if [ -n "$qualifier" ]; then
|
|
target="$target.$qualifier"
|
|
fi
|
|
if [ -n "$extension" ]; then
|
|
target="$target.$extension"
|
|
else
|
|
target="$target.$orig_extension"
|
|
fi
|
|
echo $target
|
|
fi
|
|
}
|
|
|
|
@command mass-crop label target {
|
|
for img in "$@"; do
|
|
without_suffix=${img%.*};
|
|
suffix=${img##*.};
|
|
id=${without_suffix##*/}
|
|
nux.log debug "Image: $img ID: $id"
|
|
img_size=$($NUX_MAGICK identify "$img" -format "%h %w" )
|
|
img_h=${img_size%% *};
|
|
img_w=${img_size##* };
|
|
i=1;
|
|
if [ -e "$ANNOTATIONS/${id}.bboxes" ]; then
|
|
grep "^$label" "$ANNOTATIONS/${id}.bboxes" | while read label cx cy w h; do
|
|
w=$(nux.round $(nux.calc "$w*$img_w") 0);
|
|
h=$(nux.round $(nux.calc "$h*$img_h") 0);
|
|
x=$(nux.round $(nux.calc "$cx*$img_w-$w*0.5") 0);
|
|
y=$(nux.round $(nux.calc "$cy*$img_h-$h*0.5") 0);
|
|
nux.fs.info "$img" "cropping ${w}x${h}+${x}+${y} to " "$target/$id.$i.$suffix"
|
|
$NUX_MAGICK convert "$img" -crop "${w}x${h}+${x}+${y}" "$target/$id.$i.$suffix"
|
|
let "i=i+1"
|
|
done;
|
|
fi
|
|
done;
|
|
|
|
|
|
|
|
}
|