Skip to content

Instantly share code, notes, and snippets.

@tomval2k
Created January 17, 2022 10:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomval2k/e227dfc09c76e51a6424b5495d5d1cda to your computer and use it in GitHub Desktop.
Save tomval2k/e227dfc09c76e51a6424b5495d5d1cda to your computer and use it in GitHub Desktop.
#!/usr/bin/awk -f
# one big assumption of aspect ration is 3:2 of height:width for the poster images
#suggested numbers for 1080x1920 to use whole screen with no padding and no spare slots
#96,216,600,864,1536
function getfilelist(){
# note the escaped double quotes inside the variable text
if (targetmax) {
SQL_LIMIT="LIMIT " targetmax;
}
sql = "'SELECT images FROM TypedBaseItems WHERE type=\"MediaBrowser.Controller.Entities.Movies.Movie\" ORDER BY RANDOM() " SQL_LIMIT ";'";
delete posterjpg[0];
count = 0;
cmd = "mkdir -p " tempdir;
cmd | getline OUTPUT;
cmd = "mkdir -p " outputdir;
cmd | getline OUTPUT;
cmd = "cp " maindb " " tempdb;
cmd | getline OUTPUT;
cmd = pathtosql " " tempdb " " sql;
while( (cmd | getline OUTPUT) > 0 ) {
match(OUTPUT, /%MetadataPath%\\library\\[a-z0-9]{2}\\[a-z0-9]{32}\\poster.jpg/, posterfilename);
# print posterfilename[0];
sub(/%MetadataPath%/, "", posterfilename[0]);
# print posterfilename[0];
gsub(/\\/, "/", posterfilename[0]);
# print posterfilename[0];
posterfilename[0] = dbpathprefix posterfilename[0];
# print posterfilename[0];
count ++;
# array index starts at '1' this way, not '0'. Good or bad...??
posterjpg[count] = posterfilename[0];
}
close(cmd);
}
function calculatestuff() {
# thumbnail has ration 3:2 same as poster (this is an assumption of unknown risk!)
# thumbnail can only be whole pixels, so round down to nearest integer
# width has to be an even number so height can be an integer without any rounding
# width also has to be greater than 0
thumbwidth = int(sqrt(targetarea / count * 2 / 3));
if(thumbwidth % 2 != 0){ --thumbwidth;}
if(!(thumbwidth > 0)){
print "thumb width too small";
exit;
}
# due to not being able to have part of an image in a row/column this area is lost and unaccounted for...
# ...so might reduce usable image space to less that of required images
# so reduce image width by 2 pixels, and recalculate until all images can fit in poster
do {
thumbheight = thumbwidth * 3 / 2;
if(!(thumbheight > 0)){
print "thumb height too small";
exit;
}
# can only have an integer of rows/columns
thumbrows = int(targetheight / thumbheight);
thumbcols = int(targetwidth / thumbwidth);
thumbcapacity = thumbrows * thumbcols;
if(thumbcapacity < count){
thumbwidth = thumbwidth - 2;
# print "now try width " thumbwidth;
}
}
while ( thumbcapacity < count);
# as we reduce thumbnail size to ensure no thumbnails are partially included and cut off by a border
# potentially create space for another row of images
# thumbcapacity must be recalculated
## while (thumbcapacity - count > thumbcols){
## thumbrows --;
## thumbcapacity = thumbrows * thumbcols;
## }
while (thumbcapacity > (count - thumbcols)){
if( (thumbcapacity - thumbcols) >= count ){
# print "if";
thumbrows --;
}
else {
break;
}
thumbcapacity = thumbrows * thumbcols;
}
thumbarea = thumbwidth * thumbheight;
unusedwidth = targetwidth - thumbcols * thumbwidth;
unusedheight = targetheight - thumbrows * thumbheight;
sparethumbs = thumbcapacity - count;
}
function cleancache(){
# could archive anything here
cmd = "rm -r " tempdir;
cmd | getline OUTPUT;
close(cmd);
}
function createthumbs(){
q = 1;
do {
cmd = pathtoconvert " -resize " thumbwidth "x" thumbheight " -quality 100 " posterjpg[q] " " tempdir q ".jpg";
cmd | getline OUTPUT;
close(cmd);
rowid = int((q - 1) / thumbcols) + 1 ;
rowofthumbpathnames[rowid] = rowofthumbpathnames[rowid] tempdir q ".jpg ";
q ++;
}
while ( q <= count )
for (i in rowofthumbpathnames){
cmd = pathtoconvert " " rowofthumbpathnames[i] " +append -quality 100 " tempdir "row-" i ".jpg";
cmd | getline OUTPUT;
close(cmd);
}
for (i=1; i <= thumbrows; i++){
allrowjpgpaths = allrowjpgpaths " " tempdir "row-" i ".jpg";
}
cmd = pathtoconvert " " allrowjpgpaths " -background black -append -quality 100 " tempdir "0.jpg";
# print cmd;
cmd | getline OUTPUT;
close(cmd);
# cmd = pathtoconvert " " tempdir "0.jpg -gravity center -background black -extent " targetwidth "x" targetheight " -quality 100 " tempdir "00.jpg";
cmd = pathtoconvert " " tempdir "0.jpg -gravity center -background black -extent " targetwidth "x" targetheight " -quality 100 " outputdir count "." targetwidth "x" targetheight "." timestamp ".jpg";
# print cmd;
cmd | getline OUTPUT;
close(cmd);
}
function dumpvariables(){
printf "%-20s %s\n", "version:",version;
printf "%-20s %s\n", "workingdir:",workingdir;
printf "%-20s %s\n", "outputdir:",outputdir;
printf "%-20s %s\n", "tempdir:",tempdir;
printf "%-20s %s\n", "tempdb:",tempdb;
# printf "%-20s %s\n", "posterlistfile:",posterlistfile;
printf "%-20s %s\n", "maindb:",maindb;
printf "%-20s %s\n", "dbpathprefix:",dbpathprefix;
printf "%-20s %s\n", "timestamp:",timestamp;
printf "%-20s %s\n", "pathtoconvert:",pathtoconvert;
printf "%-20s %s\n", "pathtosql:",pathtosql;
printf "%-20s %s\n", "targetwidth:",targetwidth;
printf "%-20s %s\n", "targetheight:",targetheight;
printf "%-20s %s\n", "targetarea:",targetarea;
# now variables that can only occur after actually doing something!!
printf "%-20s %s\n", "postercount:",count;
for (i in posterjpg){
# printf "%-20s %s\n", "\tposterjpg:",posterjpg[i];
}
printf "%-20s %s\n", "thumbarea:",thumbarea;
printf "%-20s %s\n", "thumbheight:",thumbheight;
printf "%-20s %s\n", "thumbwidth:",thumbwidth;
printf "%-20s %s\n", "thumbrows:",thumbrows;
printf "%-20s %s\n", "thumbcols:",thumbcols;
printf "%-20s %s\n", "thumbcapacity:",thumbcapacity;
printf "%-20s %s\n", "unusedwidth:",unusedwidth;
printf "%-20s %s\n", "unusedheight:",unusedheight;
printf "%-20s %s\n", "sparethumbs:",sparethumbs;
}
function readuserinput(){
for (i in ARGV){
if (ARGV[i] ~ /^(--)?help$/ ) {
print "Err...help is not coming yet. Meh.";
exit;
}
else if (ARGV[i] ~ /^max=/ ) {
usermax = ARGV[i];
gsub(/^.*=/, "", usermax);
if( ! match(usermax, /^[0-9]+$/)) {
print "max must be an integer";
doexit=1;
}
else {
targetmax=usermax;
}
}
else if (ARGV[i] ~ /^width=/ ) {
userwidth = ARGV[i];
gsub(/^.*=/, "", userwidth);
if( ! match(userwidth, /^[0-9]+$/)) {
print "width must be an integer";
doexit=1;
}
else {
targetwidth=userwidth;
}
}
else if (ARGV[i] ~ /^height=/ ) {
userheight = ARGV[i];
gsub(/^.*=/, "", userheight);
if( ! match(userheight, /^[0-9]+$/)) {
print "height must be an integer";
doexit=1;
}
else {
targetheight=userheight;
}
}
else if (ARGV[i] ~ /^dbpath=/ ) {
userdb = ARGV[i];
gsub(/^.*=/, "", userdb);
if(! (userdb)){
print "dbpath must be something";
doexit=1;
}
else {
maindb = userdb;
}
}
else if (ARGV[i] ~ /^workingdir=/ ) {
userworkingdir = ARGV[i];
gsub(/^.*=/, "", userworkingdir);
if(! (userworkingdir)){
print "workingdir must be something";
doexit=1;
}
else {
workingdir = userworkingdir;
}
}
else if (ARGV[i] ~ /^outputdir=/ ) {
useroutputdir = ARGV[i];
gsub(/^.*=/, "", useroutputdir);
if(! (useroutputdir)){
print "outputdir must be something";
doexit=1;
}
else {
outputdir = useroutputdir;
}
}
else if (ARGV[i] ~ /^dbpathprefix=/ ) {
userdbpathprefix = ARGV[i];
gsub(/^.*=/, "", userdbpathprefix);
if(! (userdbpathprefix)){
print "dbpathprefix must be something";
doexit=1;
}
else {
dbpathprefix = userdbpathprefix;
}
}
# else{
# printf "%-20s %s\n", "Unrecognised input:",ARGV[i];
# }
}
if( doexit ){
print "yeah bye";
exit;
}
# printf "%-20s %s\n", "usermax:",usermax;
# printf "%-20s %s\n", "userwidth:",userwidth;
# printf "%-20s %s\n", "userheight:",userheight;
# printf "%-20s %s\n", "userdb:",userdb;
# printf "%-20s %s\n", "userworkingdir:",userworkingdir;
# printf "%-20s %s\n", "useroutputdir:",useroutputdir;
# printf "%-20s %s\n", "userdbpathprefix:",userdbpathprefix;
}
BEGIN {
version = "0.4";
# default values
workingdir = "/mnt/d/jellyfin/mega-poster/";
outputdir = workingdir "posters/";
tempdir = workingdir "cache/";
tempdb = tempdir "lib.db";
# posterlistfile = tempdir "poster.list";
maindb = "/mnt/d/jellyfin/Server/data/library.db";
dbpathprefix = "/mnt/d/jellyfin/Server/metadata";
timestamp = strftime("%Y-%m-%d.%H-%M-%S");
pathtoconvert = "/usr/bin/convert";
pathtosql = "/usr/bin/sqlite3";
targetwidth = 1920;
targetheight = 1080;
readuserinput();
targetarea = targetheight * targetwidth;
cleancache();
getfilelist();
calculatestuff();
dumpvariables();
createthumbs();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment