60 Commits

Author SHA1 Message Date
05d77ae5b8 update release name 2023-06-10 08:32:02 +02:00
9795034d74 bugfix of output not always being shown 2023-06-10 08:25:00 +02:00
c01948dc3f fix lots of GUI bugs + styling a lil 2023-06-09 17:03:25 +02:00
73661fae19 fix cli crash if engine does not exist in -d flag 2023-06-09 15:49:38 +02:00
739f17283f make cli output better 2023-06-09 15:40:58 +02:00
a3d1362d50 fix bug with fsr upscaler on windows 2023-06-09 15:38:37 +02:00
573450dee9 add debug code 2023-06-09 14:59:02 +02:00
janis
ad64287a8a make cli output better 2023-06-09 09:52:43 +02:00
janis
9569e46b75 fix defaults 2023-06-09 09:45:28 +02:00
janis
506baf2cd3 fix ffc cli option 2023-06-09 09:44:44 +02:00
f0346465fd update package script for new shell 2023-06-08 09:33:25 +02:00
600fbc8cc7 fix packaging info 2023-06-08 09:01:02 +02:00
30c6e353c9 update logo & package.json of gui 2023-06-07 20:29:53 +02:00
ecd654abd9 remove note on new logo needed, as new logo here 2023-06-07 20:22:57 +02:00
04e77906a7 slightly adapt logo 2023-06-07 20:21:38 +02:00
3091b4baca add bew kigi 2023-06-07 20:18:27 +02:00
4e902360b7 fix not working badge 2023-06-07 20:04:22 +02:00
8669ff0ee2 Fix some more wrong names & update Readme 2023-06-07 20:02:18 +02:00
bb44362a3e fix name wrong 2023-06-07 19:59:35 +02:00
d19435277f add various fixes for bugs 2023-06-07 19:57:31 +02:00
98f2ec28ce update build scripts 2023-06-07 13:26:43 +02:00
b79e206f0d add relative path call for engines 2023-06-07 12:13:30 +02:00
7377625812 fix bug that only occurs on windows 2023-06-07 11:54:38 +02:00
janis
7299250437 fix crash of CLI when no input file specified 2023-06-07 09:04:04 +02:00
janis
ce284540a6 clean up windows files with stop script 2023-06-07 09:01:47 +02:00
janis
d187a70452 bugfix + better py for win install script 2023-06-07 08:40:54 +02:00
7ef00cee24 fix notifications 2023-06-05 13:36:24 +02:00
9bad807528 add error reporting 2023-06-05 13:34:26 +02:00
9f29990faf automatically add output path 2023-06-05 08:49:11 +02:00
842db05488 fix spec file for pyinstaller 2023-06-05 08:36:55 +02:00
bf30e40759 rename project, fix bug & optional output path 2023-06-05 08:24:33 +02:00
Janis Hutz
c977c9e754 Update HomeView.vue
Fix multiline text of cmd output
2023-06-04 18:40:04 +02:00
8f7f6d71b7 removed express backend & added new ipc 2023-06-04 17:35:10 +02:00
b28d2dd68e move to new port 2023-06-04 16:14:28 +02:00
f199fbded3 add more convenience scripts 2023-06-04 15:56:38 +02:00
de096496c7 add most recent usage for CLI 2023-06-04 15:44:05 +02:00
ab6d07d4bd add independent packaging scripts 2023-06-04 15:43:21 +02:00
0ea2d1d375 finish packaging script 2023-06-04 15:10:48 +02:00
69205a1d8a add python wine installer 2023-06-04 14:49:05 +02:00
60ffb862dc add socket.io 2023-06-04 14:44:13 +02:00
9fabb64161 package script update 2023-06-04 11:58:03 +02:00
e247d7a524 update package script 2023-06-04 11:16:46 +02:00
430c271f62 add build script 2023-06-04 11:04:15 +02:00
41b8dd6d03 add electron forge + fixes 2023-06-04 10:40:54 +02:00
e3d1ff1228 fix image upscaling 2023-06-04 10:05:17 +02:00
bf2931085f possibly working GUI, compiling missing 2023-06-03 11:34:39 +02:00
janis
58e114e368 begin implementation of plugin downloader 2023-05-31 14:27:17 +02:00
janis
9eee7a9878 add engine loading (technically) 2023-05-31 14:18:51 +02:00
janis
5099959082 fix error, remove stuff, add stuff 2023-05-31 14:06:04 +02:00
bf4e85f6c1 add settings page (frontend currently broken!) 2023-05-31 12:00:35 +02:00
Janis Hutz
619e24d332 Update README.md
Add infos about new name
2023-05-31 08:41:54 +02:00
efc15a45cd add version fetching 2023-05-30 21:11:21 +02:00
Janis Hutz
fcddfd6292 Merge pull request #15 from simplePCBuilding/dev-V1.1
create about page
2023-05-30 14:17:28 +02:00
Janis Hutz
72bcaa3131 Merge pull request #14 from simplePCBuilding/simplePCBuilding-patch-2
Update README.md
2023-05-30 14:15:29 +02:00
Janis Hutz
d2a4ddc5ec Update README.md 2023-05-30 14:15:20 +02:00
Janis Hutz
d9ea3774c9 Merge pull request #13 from simplePCBuilding/simplePCBuilding-patch-1
Update package.json
2023-05-30 14:10:50 +02:00
Janis Hutz
942c234931 Update package.json 2023-05-30 14:10:39 +02:00
Janis Hutz
ccd50e2cf4 Add more badges to README.md 2023-05-30 14:09:47 +02:00
Janis Hutz
bcf8c0be3d Update README.md 2023-05-30 13:55:29 +02:00
Janis Hutz
f5edfa8109 Merge pull request #12 from simplePCBuilding/dev-V1.1
Merge dev V1.1
2023-05-29 18:58:04 +00:00
47 changed files with 1256 additions and 247 deletions

View File

@@ -1,7 +0,0 @@
[Desktop Entry]
Type=Application
Name=Image & Video Upscaler
Comment=Upscale your videos and images with different upscalers
Path=/opt/imagevideoupscaler
Exec=/opt/imagevideoupscaler/imagevideoupscaler
Icon=imagevideoupscaler

2
.gitignore vendored
View File

@@ -1,5 +1,5 @@
# #
# FSRImageVideoUpscalerFrontend - .gitignore # SimpleMediaUpscalerLite - .gitignore
# #
# Created by Janis Hutz 05/24/2023, Licensed under the GPL V3 License # Created by Janis Hutz 05/24/2023, Licensed under the GPL V3 License
# https://janishutz.com, development@janishutz.com # https://janishutz.com, development@janishutz.com

View File

@@ -631,7 +631,8 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found. the "copyright" line and a pointer to where the full notice is found.
A simple PyQT5 frontend to upscale both videos and images A simple Electron GUI and Python CLI to upscale your videos using different
upscaling engines.
Copyright (C) 2023 Janis Hutz Copyright (C) 2023 Janis Hutz
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@@ -652,7 +653,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode: notice like this when it starts in an interactive mode:
ImageVideoUpscalerFrontend Copyright (C) 2023 Janis Hutz SimpleMediaUpscalerLite Copyright (C) 2023 Janis Hutz
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details. under certain conditions; type `show c' for details.

View File

@@ -1,19 +1,28 @@
<div id="title" align="center"> <div id="title" align="center">
<img src="./logo.png" width="300"> <img src="./logo.png" width="300">
<h1>ImageVideoUpscalerFrontend</h1> <h1>SimpleMediaUpscalerLite</h1>
</div> </div>
<div id="badges" align="center"> <div id="badges" align="center">
<img src="https://img.shields.io/github/release/simplePCBuilding/FSRImageVideoUpscalerFrontend.svg"> <img src="https://img.shields.io/github/license/simplePCBuilding/SimpleMediaUpscalerLite.svg">
<img src="https://img.shields.io/github/license/simplePCBuilding/FSRImageVideoUpscalerFrontend.svg"> <img src="https://img.shields.io/github/repo-size/simplePCBuilding/SimpleMediaUpscalerLite.svg">
<img src="https://img.shields.io/github/repo-size/simplePCBuilding/FSRImageVideoUpscalerFrontend.svg"> <img alt="Lines of code" src="https://img.shields.io/tokei/lines/github/simplePCBuilding/SimpleMediaUpscalerLite">
<img src="https://img.shields.io/tokei/lines/github/simplePCBuilding/FSRImageVideoUpscalerFrontend"> <img src="https://img.shields.io/github/languages/top/simplePCBuilding/SimpleMediaUpscalerLite">
<img src="https://img.shields.io/github/issues-pr-raw/simplePCBuilding/FSRImageVideoUpscalerFrontend"> <img src="https://img.shields.io/github/directory-file-count/simplePCBuilding/SimpleMediaUpscalerLite.svg">
<img src="https://img.shields.io/github/languages/top/simplePCBuilding/FSRImageVideoUpscalerFrontend"> <br>
<img src="https://img.shields.io/github/directory-file-count/simplePCBuilding/FSRImageVideoUpscalerFrontend.svg"> <img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/simplePCBuilding/SimpleMediaUpscalerLite">
<img src="https://img.shields.io/github/package-json/v/simplePCBuilding/FSRImageVideoUpscalerFrontend.svg"> <img alt="GitHub watchers" src="https://img.shields.io/github/watchers/simplePCBuilding/SimpleMediaUpscalerLite">
<img src="https://img.shields.io/github/issues-pr-raw/simplePCBuilding/SimpleMediaUpscalerLite">
<img alt="GitHub forks" src="https://img.shields.io/github/forks/simplePCBuilding/SimpleMediaUpscalerLite">
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/simplePCBuilding/SimpleMediaUpscalerLite">
<br>
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/simplePCBuilding/SimpleMediaUpscalerLite/total?label=Downloads (total)">
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/downloads/simplePCBuilding/SimpleMediaUpscalerLite/latest/total?label=Downloads (latest)">
<img src="https://img.shields.io/github/release/simplePCBuilding/SimpleMediaUpscalerLite.svg">
<img src="https://img.shields.io/github/package-json/v/simplePCBuilding/SimpleMediaUpscalerLite.svg?label=Development Version">
</div> </div>
An Electron App with Python CLI to upscale images and videos using multiple different upscaling engines. smuL (pronounced like "small") is an Electron App with Python CLI to upscale images and videos using multiple different upscaling engines.
# Functionality # Functionality
This app allows you to fully automatically upscale a single file or a full on folder with one of many different engines. This app allows you to fully automatically upscale a single file or a full on folder with one of many different engines.
@@ -31,13 +40,33 @@ This app allows you to fully automatically upscale a single file or a full on fo
- more to come! - more to come!
This App also features a CLI interface. This App also features a CLI interface.
- Options:
``` ```
-s SCALEFACTOR --scalefactor SCALEFACTOR Factor of form 2x, maximum 4x usage: SimpleMediaUpscalerLite-cli.py [-h] [-i INPUTFILE] [-o OUTPUTFILE] [-s SCALEFACTOR] [-S SHARPENING] [-T THREADS] [-E ENGINE] [-M MODE] [-F FILETYPE] [-d DETAILS] [-p] [-v]
-S SHARPENING --sharpening SHARPENING Value (0 - 1)
-T THREADCOUNT --threads THREADCOUNT Choose how many threads in parallel. Maximum is max threads of your CPU SimpleMediaUpscalerLite - CLI, a CLI application to upscale videos and images using different upscaling engines.
-F FILETYPE --filetype FILETYPE Choose file type of temporary image files when upscaling videos (required)
-N --noscaling No upscaling, requires -S option (Sharpening option) options:
-h, --help show this help message and exit
-i INPUTFILE, --inputfile INPUTFILE
File path for the video / image to be upscaled
-o OUTPUTFILE, --outputfile OUTPUTFILE
Output file path for the video / image that was upscaled
-s SCALEFACTOR, --scalefactor SCALEFACTOR
Scale factor for the video / image. Can be a integer from -4 to 4
-S SHARPENING, --sharpening SHARPENING
Sharpening factor (between 0 and 1 whereas 0 means no sharpening, 1 the most sharpening. Recommendation: Do not exceed 0.25, as it often looks bad)
-T THREADS, --threads THREADS
Thread count to use. Cannot exceed CPU thread count. Scaling non-linear (using 2 threads is not exactly 2x the speed of 1 thread). Scales well with FSR, barely with
Real-ESRGAN, as it uses mostly the GPU to upscale
-E ENGINE, --engine ENGINE
Upscaling engine. By default can be fsr or ss. Use the -p option to see all installed engines
-M MODE, --mode MODE Specify a special mode for a specific engine. Might not be available in every engine. Use the -d option to find out more
-F FILETYPE, --filetype FILETYPE
Change the file type of the temporary image files. Supports png, jpg. Video quality: png > jpg. PNG is default, if not specified.
-d DETAILS, --details DETAILS
Get details on usage of a particular engine and exit. Reads the config.json file of that engine and displays it in a HR manner
-p, --printengines Print all engines and exit
-v, --version Print version and exit
``` ```
# Supported OS # Supported OS
@@ -47,25 +76,26 @@ This App also features a CLI interface.
# Contributing # Contributing
If you have any suggestions or features you'd like to have implemented, you may either implement the feature yourself and open a pull request, or open an issue on this GitHub page. Both things are appreciated! If you have any suggestions or features you'd like to have implemented, you may either implement the feature yourself and open a pull request, or open an issue on this GitHub page. Both things are appreciated!
*I am looking for somebody willing to maintain the Windows version (including installer) as I am running Linux*
--> Follow the rules layed out in CONTRIBUTING.md --> Follow the rules layed out in CONTRIBUTING.md
--> We will add a linter that will then run on circleci to ensure code quality is high --> We will add a linter that will then run on circleci to ensure code quality is high
### Current Contributers ### Current Contributers
- simplePCBuilding (Maintainer) [Core (CLI), Docs, Website, Frontend, Linux packages] - simplePCBuilding (Maintainer) [Core (CLI), Docs, Website, Frontend, Linux packages]
- ThatPlasma (Testing, Packager) [Testing, Windows Package] - ThatPlasma (Testing, Packager) [Testing]
# Roadmap # Roadmap
V1.1.0: V2.0.0:
- Migrate to PyQt5 (or create Electron app and make python app CLI only) - Migrate to Electron app -- ✅
- Create Windows & Mac Version - Package Windows & Linux Version -- ✅
- Refactor backend to add plugin support - Add packaging script for Linux & Windows version -- ✅
- Add more scaling engines - Make python app CLI only -- ✅
- Expand Wiki to feature documentation on how to create a plugin (and maybe add a project website) - Refactor backend to add plugin support -- ✅
V1.2.0: V2.1.0:
- Add more scaling engines
- Expand Wiki to feature documentation on how to create a plugin (and maybe add a project website)
- Show progress of scaling - Show progress of scaling
# Issues # Issues
@@ -73,6 +103,7 @@ If you encounter any problems with this app, please don't hesitate to open an is
## Known issues ## Known issues
- Electron App is not available yet - Electron App is not available yet
- Electron App shows that it is out of date if running in the development version
- GTK version only runs on Linux - GTK version only runs on Linux
# FAQ # FAQ
@@ -88,7 +119,7 @@ If the OS is not officially supported, we may not be able to help you, since we
**Q: Why no worky on MacOS? / Can you port to MacOS?** **Q: Why no worky on MacOS? / Can you port to MacOS?**
A: MacOS cannot run some of the upscalers included by default so we cannot support it. If you find a way to run all upscalers on Mac, feel free to open a PR to add that functionality A: Wine support on MacOS is still mediocre and most likely cannot run some of the upscalers included by default so we cannot support it. I will be testing it at some point in a VM, but that won't necesarily speak for full functionality. If you find a way to run all upscalers on Mac, feel free to open a PR to add that functionality or just let us know what you did in an issue.
**Q: Upscaled XXX looks not as great as I want** **Q: Upscaled XXX looks not as great as I want**
@@ -96,4 +127,4 @@ A: Try out different engines (that's why we support so many) and try to use shar
**Q: How can I support you?** **Q: How can I support you?**
A: You may contribute to this project by writing documentation, improving the website, adding plugins, fixing bugs, testing or by donating. A: You may contribute to this project by writing documentation, improving the website, adding plugins, fixing bugs, testing or by donating.

View File

@@ -1,5 +1,5 @@
{ {
"abbr":"FSR", "abbr":"ffc",
"displayName":"FidelityFX_CLI", "displayName":"FidelityFX_CLI",
"lastUsedFilePath":"sc", "lastUsedFilePath":"sc",
"fileNameBeginning":"ig", "fileNameBeginning":"ig",
@@ -11,5 +11,7 @@
"pluginCreator": "Janis Hutz", "pluginCreator": "Janis Hutz",
"pluginCreatorLink": "https://janishutz.com", "pluginCreatorLink": "https://janishutz.com",
"engineLink": "", "engineLink": "",
"supports": [ "upscaling", "sharpening" ] "supports": [ "upscaling", "sharpening" ],
"engineDownloadLink":"",
"filesToInclude": [ "ffc.py" ]
} }

View File

@@ -11,30 +11,60 @@ class Scaler:
self.tmppath = '' self.tmppath = ''
self.videometa = {} self.videometa = {}
def singleScaler ( self, input_path, output_path, scalefactor, threads, mode ): def singleScaler ( self, input_path, output_path, scalefactor, sharpening, threads, mode, tmppath ):
if self.os_type == 'linux': scaler = 'FSR'
self.command = f'wine ./bin/lib/FidelityFX_CLI.exe -Mode { mode } -Scale {scalefactor} {scalefactor} {input_path} {output_path}' if ( mode.upper() == 'HQC' ):
elif self.os_type == 'win32': scaler = 'HighQualityCubic'
self.command = f'FidelityFX_CLI -Mode { mode } -Scale {scalefactor} {scalefactor} {input_path} {output_path}' elif ( mode.upper() == 'C' ):
scaler = 'Cubic'
if ( sharpening == 0 ):
output = output_path
elif ( scalefactor != 0 and sharpening != 0 ):
output = tmppath + 'tmpImage.' + output_path.split( '.' )[ 1 ]
else: else:
print( 'OS CURRENTLY UNSUPPORTED!' ) output = input_path
return False
if ( scalefactor != 0 ):
if self.os_type == 'linux':
self.command = f'wine ./bin/lib/FidelityFX_CLI.exe -Mode { scaler } -Scale {scalefactor}x {scalefactor}x {input_path} {output}'
elif self.os_type == 'win32':
self.command = f'bin\\lib\\FidelityFX_CLI.exe -Mode { scaler } -Scale {scalefactor}x {scalefactor}x {input_path} {output}'
else:
print( 'OS CURRENTLY UNSUPPORTED!' )
return False
os.system( self.command )
if ( sharpening != 0 ):
if self.os_type == 'linux':
self.command = f'wine ./bin/lib/FidelityFX_CLI.exe -Mode CAS -Sharpness {sharpening} {output} {output_path}'
elif self.os_type == 'win32':
self.command = f'bin\\lib\\FidelityFX_CLI.exe -Mode CAS -Sharpness {sharpening} {output} {output_path}'
else:
print( 'OS CURRENTLY UNSUPPORTED!' )
return False
os.system( self.command )
os.system( self.command ) print( '\n\n==> Photo upscaled' );
print( '\n\n==>Photo upscaled' ); return True
def videoScaler ( self, tmppath, threads, scalefactor, sharpening, filetype, mode ): def videoScaler ( self, tmppath, threads, scalefactor, sharpening, filetype, mode ):
self.isScaling = True self.isScaling = True
if ( scalefactor == 0 or scalefactor == None ): if ( scalefactor == 0 or scalefactor == None ):
self.isScaling = False self.isScaling = False
self.isSharpening = True
if sharpening != 0 and sharpening != None:
self.isSharpening = False
# Locate Images and assemble FSR-Command # Locate Images and assemble FSR-Command
self.file_list = [] self.file_list = []
self.filelist = os.listdir( tmppath ) self.filelist = os.listdir( tmppath )
self.filelist.pop(0) self.filelist.pop(0)
self.filelist.sort() self.filelist.sort()
self.number = 0 self.number = 0
if sharpening != 0 and sharpening != None: if self.isSharpening:
for self.file in self.filelist: for self.file in self.filelist:
self.number += 1 self.number += 1
if ( self.os_type == 'win32' ): if ( self.os_type == 'win32' ):
@@ -90,14 +120,14 @@ class Scaler:
if ( i == self.threads - 1 ): if ( i == self.threads - 1 ):
for element in self.file_list: for element in self.file_list:
self.files += element; self.files += element;
self.command_list.append( ( self.files, scalefactor, i, self.maxlength, self.os_type, mode ) ) self.command_list.append( ( self.files, scalefactor, i, self.maxlength, self.os_type, mode, self.isSharpening ) )
self.pool = multiprocessing.Pool( self.threads ) self.pool = multiprocessing.Pool( self.threads )
self.pool.starmap( upscalerEngine, self.command_list ); self.pool.starmap( upscalerEngine, self.command_list );
self.pool.close(); self.pool.close();
self.pool.join(); self.pool.join();
if sharpening != 0 and sharpening != None: if self.isSharpening:
print( f'\n\n\n==> Sharpening using { self.threads } threads <==\n\n' ); print( f'\n\n\n==> Sharpening using { self.threads } threads <==\n\n' );
time.sleep( 2 ); time.sleep( 2 );
@@ -153,7 +183,10 @@ class Scaler:
# Add return values # Add return values
def upscalerEngine ( files, scalefactor, number, maxlength, os_type, version ): def upscalerEngine ( files, scalefactor, number, maxlength, os_type, version, isSharpening ):
comparison = 'sc'
if ( isSharpening ):
comparison = 'up'
scaler = 'FSR' scaler = 'FSR'
if ( version.upper() == 'HQC' ): if ( version.upper() == 'HQC' ):
scaler = 'HighQualityCubic' scaler = 'HighQualityCubic'
@@ -167,7 +200,7 @@ def upscalerEngine ( files, scalefactor, number, maxlength, os_type, version ):
while files[maxlength - pos:maxlength - pos + 1] != ' ': while files[maxlength - pos:maxlength - pos + 1] != ' ':
pos += 1 pos += 1
file_processing = files[:maxlength - pos] file_processing = files[:maxlength - pos]
if file_processing[len(file_processing) - 14:len(file_processing) - 12] == 'ig': if file_processing[len(file_processing) - 17:len(file_processing) - 15] != comparison:
pos += 5 pos += 5
else: else:
pass pass
@@ -187,7 +220,7 @@ def upscalerEngine ( files, scalefactor, number, maxlength, os_type, version ):
while files[posy - pos:posy - pos + 1] != ' ': while files[posy - pos:posy - pos + 1] != ' ':
pos += 1 pos += 1
file_processing = files[posx:posy - pos] file_processing = files[posx:posy - pos]
if file_processing[len(file_processing) - 14:len(file_processing) - 12] == 'ig': if file_processing[len(file_processing) - 17:len(file_processing) - 15] != comparison:
pos += 5 pos += 5
while files[posy - pos:posy - pos + 1] != ' ': while files[posy - pos:posy - pos + 1] != ' ':
pos += 1 pos += 1
@@ -209,7 +242,7 @@ def upscalerEngine ( files, scalefactor, number, maxlength, os_type, version ):
if os_type == 'linux': if os_type == 'linux':
command_us = f'wine ./bin/lib/FidelityFX_CLI.exe -Mode { scaler } -Scale {scalefactor}x {scalefactor}x {files_handle}' command_us = f'wine ./bin/lib/FidelityFX_CLI.exe -Mode { scaler } -Scale {scalefactor}x {scalefactor}x {files_handle}'
elif os_type == 'win32': elif os_type == 'win32':
command_us = f'FidelityFX_CLI -Mode { scaler } -Scale {scalefactor}x {scalefactor}x {files_handle}' command_us = f'bin\\lib\\FidelityFX_CLI.exe -Mode { scaler } -Scale {scalefactor}x {scalefactor}x {files_handle}'
else: else:
print( 'OS CURRENTLY UNSUPPORTED!' ) print( 'OS CURRENTLY UNSUPPORTED!' )
return False return False
@@ -235,7 +268,7 @@ def sharpeningEngine ( files, number, maxlength, os_type, sharpening, didUpscale
pos += 1 pos += 1
file_processing = files[:maxlength - pos] file_processing = files[:maxlength - pos]
if ( didUpscale ): if ( didUpscale ):
if file_processing[len(file_processing) - 14:len(file_processing) - 12] == 'up': if file_processing[len(file_processing) - 17:len(file_processing) - 15] == 'up':
pos += 5 pos += 5
else: else:
if file_processing[len(file_processing) - 17:len(file_processing) - 15] == 'ru': if file_processing[len(file_processing) - 17:len(file_processing) - 15] == 'ru':
@@ -283,7 +316,7 @@ def sharpeningEngine ( files, number, maxlength, os_type, sharpening, didUpscale
if os_type == 'linux': if os_type == 'linux':
command_sharpening = f'wine ./bin/lib/FidelityFX_CLI.exe -Mode CAS -Sharpness {sharpening} {files_handle}' command_sharpening = f'wine ./bin/lib/FidelityFX_CLI.exe -Mode CAS -Sharpness {sharpening} {files_handle}'
elif os_type == 'win32': elif os_type == 'win32':
command_sharpening = f'FidelityFX_CLI -Mode CAS -Sharpness {sharpening} {files_handle}' command_sharpening = f'bin\\lib\\FidelityFX_CLI.exe -Mode CAS -Sharpness {sharpening} {files_handle}'
else: else:
print( 'OS CURRENTLY UNSUPPORTED!' ) print( 'OS CURRENTLY UNSUPPORTED!' )
return False return False

View File

@@ -10,5 +10,7 @@
"pluginCreator": "Janis Hutz", "pluginCreator": "Janis Hutz",
"pluginCreatorLink": "https://janishutz.com", "pluginCreatorLink": "https://janishutz.com",
"engineLink": "", "engineLink": "",
"supports": [ "upscaling" ] "supports": [ "upscaling" ],
"engineDownloadLink":"",
"filesToInclude": [ "fsr.py" ]
} }

View File

@@ -11,17 +11,19 @@ class Scaler:
self.tmppath = "" self.tmppath = ""
self.videometa = {} self.videometa = {}
def singleScaler ( self, input_path, output_path, scalefactor, threads, mode ): def singleScaler ( self, input_path, output_path, scalefactor, sharpening, threads, mode, tmppath ):
modes = { 'av3':'realesr-animevideov3', 'x4plus': 'realesrgan-x4plus-anime' }
if self.os_type == 'linux': if self.os_type == 'linux':
self.command = f'wine ./bin/lib/FidelityFX_CLI.exe -Scale {scalefactor} {scalefactor} {input_path} {output_path} -n { mode }' self.command = f'wine ./bin/lib/realesrgan-ncnn-vulkan.exe -i {input_path} -o {output_path} -s {scalefactor} -j {threads}:{threads}:{threads} -n { modes[ mode ] }'
elif self.os_type == 'win32': elif self.os_type == 'win32':
self.command = f'realesrgan-ncnn-vulkan -i {input_path} -o {output_path} -s {scalefactor} -j {threads}:{threads}:{threads} -n { mode }' self.command = f'bin\\lib\\realesrgan-ncnn-vulkan.exe -i {input_path} -o {output_path} -s {scalefactor} -j {threads}:{threads}:{threads} -n { modes[ mode ] }'
else: else:
print( 'OS CURRENTLY UNSUPPORTED!' ) print( 'OS CURRENTLY UNSUPPORTED!' )
return False return False
os.system( self.command ) os.system( self.command )
print( '\n\n==>Photo upscaled' ); print( '\n\n==>Photo upscaled' );
return True;
def videoScaler ( self, tmppath, threads, scalefactor, sharpening, filetype, mode ): def videoScaler ( self, tmppath, threads, scalefactor, sharpening, filetype, mode ):
modes = { 'av3':'realesr-animevideov3', 'x4plus': 'realesrgan-x4plus-anime' } modes = { 'av3':'realesr-animevideov3', 'x4plus': 'realesrgan-x4plus-anime' }
@@ -33,7 +35,7 @@ class Scaler:
except FileExistsError: except FileExistsError:
pass pass
if ( self.os_type == 'win32' ): if ( self.os_type == 'win32' ):
self.command = f'realesrgan-ncnn-vulkan -i {tmppath} -o {tmppath}sc -s {scalefactor} -j {threads}:{threads}:{threads} -n {modes[ mode ]}' self.command = f'bin\\lib\\realesrgan-ncnn-vulkan.exe -i {tmppath} -o {tmppath}sc -s {scalefactor} -j {threads}:{threads}:{threads} -n {modes[ mode ]}'
elif ( self.os_type == 'linux' ): elif ( self.os_type == 'linux' ):
self.command = f'wine ./bin/lib/realesrgan-ncnn-vulkan.exe -i {tmppath} -o {tmppath}sc -s {scalefactor} -j {threads}:{threads}:{threads} -n {modes[ mode ]}' self.command = f'wine ./bin/lib/realesrgan-ncnn-vulkan.exe -i {tmppath} -o {tmppath}sc -s {scalefactor} -j {threads}:{threads}:{threads} -n {modes[ mode ]}'
os.system( self.command ); os.system( self.command );

View File

@@ -1,5 +1,5 @@
''' '''
* FSRImageVideoUpscalerFrontend - handler.py * SimpleMediaUpscalerLite - handler.py
* *
* Created by Janis Hutz 03/14/2023, Licensed under the GPL V3 License * Created by Janis Hutz 03/14/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com * https://janishutz.com, development@janishutz.com
@@ -17,11 +17,16 @@ import json
import importlib import importlib
import shutil import shutil
import time import time
import tempfile
importedModules = {} importedModules = {}
engineList = os.listdir( 'bin/engines' ); engineList = os.listdir( 'bin/engines' );
engineList.pop( 0 ) counter = 0;
for element in engineList:
if ( element == '__pycache__' ):
engineList.pop( counter );
counter += 1;
for element in engineList: for element in engineList:
importedModules[ element ] = importlib.import_module( 'bin.engines.' + element + '.' + element ).Scaler() importedModules[ element ] = importlib.import_module( 'bin.engines.' + element + '.' + element ).Scaler()
@@ -43,12 +48,12 @@ class Handler:
def handler( self, filepath, scalefactor, output_path, sharpening, filetype, engine, mode, threads=4 ): def handler( self, filepath, scalefactor, output_path, sharpening, filetype, engine, mode, threads=4 ):
# Function to be called when using this class as this function automatically determines if file is video or image # Function to be called when using this class as this function automatically determines if file is video or image
print( '\n\n ImageVideoUpscaler - V1.1.0\n\n(c) 2023 ImageVideoUpscaler contributors\n\n\n\n' ); print( '\n\n SimpleMediaUpscalerLite - V1.1.0\n\n(c) 2023 SimpleMediaUpscalerLite contributors\n\n\n\n' );
if self.os_type == 'linux': if self.os_type == 'linux':
self.tmppath = config['PathSettings']['tmpPathLinux'] self.tmppath = tempfile.gettempdir()
elif self.os_type == 'win32': elif self.os_type == 'win32':
self.tmppath = config['PathSettings']['tmpPathWindows'] self.tmppath = tempfile.gettempdir()
else: else:
print('OS CURRENTLY UNSUPPORTED!') print('OS CURRENTLY UNSUPPORTED!')
return False return False
@@ -67,27 +72,7 @@ class Handler:
self.filepath += '\ ' self.filepath += '\ '
else: else:
self.filepath += self.letter self.filepath += self.letter
# Determining filetype
if str(filepath)[len(filepath) - 4:] == '.mp4' or str(filepath)[len(filepath) - 4:] == '.mkv' or str(filepath)[len(filepath) - 4:] == '.MP4':
print( '\n\n==> Upscaling video' )
self.video_scaling( filepath, output_path, scalefactor, threads, sharpening, filetype, mode, engine )
elif str(filepath)[len(filepath) - 4:] == '.JPG' or str(filepath)[len(filepath) - 4:] == '.png' or str(filepath)[len(filepath) - 4:] == '.jpg' or str(filepath)[len(filepath) - 5:] == '.jpeg':
print( '\n==>upscaling image' )
self.photo_scaling( scalefactor, output_path, engine )
else:
print('not supported')
return False
def photo_scaling(self, scalefactor, output_path, engine, mode):
# DO NOT CALL THIS! Use Handler().handler() instead!
pass
def video_scaling( self, input_path, output_path, scalefactor, threads, sharpening, filetype, mode, engine ):
self.engineSetting = json.load( open( 'bin/engines/' + engine + '/config.json' ) )
# DO NOT CALL THIS! Use Handler().handler() instead!
# Splitting video into frames
try: try:
shutil.rmtree(self.tmppath) shutil.rmtree(self.tmppath)
except FileNotFoundError: except FileNotFoundError:
@@ -97,6 +82,27 @@ class Handler:
except FileExistsError: except FileExistsError:
print( '==> ERROR: Temp path does not exist! <==' ) print( '==> ERROR: Temp path does not exist! <==' )
return False return False
# Determining filetype
if str(filepath)[len(filepath) - 4:] == '.mp4' or str(filepath)[len(filepath) - 4:] == '.mkv' or str(filepath)[len(filepath) - 4:] == '.MP4':
print( '\n\n==> Upscaling video' )
return self.video_scaling( filepath, output_path, scalefactor, threads, sharpening, filetype, mode, engine )
elif str(filepath)[len(filepath) - 4:] == '.JPG' or str(filepath)[len(filepath) - 4:] == '.png' or str(filepath)[len(filepath) - 4:] == '.jpg' or str(filepath)[len(filepath) - 5:] == '.jpeg':
print( '\n==> Upscaling Image' )
return self.photo_scaling( filepath, output_path, scalefactor, sharpening, threads, engine, mode )
else:
print('not supported')
return False
def photo_scaling(self, input_path, output_path, scalefactor, sharpening, threads, engine, mode ):
# DO NOT CALL THIS! Use Handler().handler() instead!
return importedModules[ engine ].singleScaler( input_path, output_path, scalefactor, sharpening, threads, mode, self.tmppath );
def video_scaling( self, input_path, output_path, scalefactor, threads, sharpening, filetype, mode, engine ):
self.engineSetting = json.load( open( 'bin/engines/' + engine + '/config.json' ) )
# DO NOT CALL THIS! Use Handler().handler() instead!
# Splitting video into frames
print( '\n==> Created directory' ) print( '\n==> Created directory' )
@@ -113,7 +119,11 @@ class Handler:
# Retrieving Video metadata # Retrieving Video metadata
self.filelist = os.listdir(self.tmppath) self.filelist = os.listdir(self.tmppath)
self.videometa = ffmpeg.probe(str(input_path))['streams'].pop(0) try:
self.videometa = ffmpeg.probe(str(input_path))['streams'].pop(0)
except Exception:
print( '\n\n==> Failed to execute ffprobe. Please ensure that you have a valid ffmpeg & ffprobe installation.\n --> Refer to our wiki for a guide on a proper installation\n\n')
return False;
self.duration = self.videometa.get( 'duration' ) self.duration = self.videometa.get( 'duration' )
self.frames = len( self.filelist ) self.frames = len( self.filelist )
@@ -162,6 +172,9 @@ class Handler:
# reassemble Video # reassemble Video
print( '\n\n==> Reassembling Video... with framerate @', self.framerate, '\n\n' ) print( '\n\n==> Reassembling Video... with framerate @', self.framerate, '\n\n' )
time.wait( 2 )
if self.os_type == 'linux': if self.os_type == 'linux':
self.command = f'ffmpeg -framerate {self.framerate} -i {self.tmppath}{self.engineSetting[ "lastUsedFilePath" ]}/{self.engineSetting[ "fileNameBeginning" ]}%08d.{filetype} {output_path} -i {self.tmppath}audio.aac' self.command = f'ffmpeg -framerate {self.framerate} -i {self.tmppath}{self.engineSetting[ "lastUsedFilePath" ]}/{self.engineSetting[ "fileNameBeginning" ]}%08d.{filetype} {output_path} -i {self.tmppath}audio.aac'
elif self.os_type == 'win32': elif self.os_type == 'win32':
@@ -169,4 +182,6 @@ class Handler:
else: else:
print( 'OS CURRENTLY UNSUPPORTED!' ); print( 'OS CURRENTLY UNSUPPORTED!' );
return False return False
os.system( self.command ) os.system( self.command )
return True;

9
bin/pluginDownloader.py Normal file
View File

@@ -0,0 +1,9 @@
"""
* SimpleMediaUpscalerLite - pluginDownloader.py
*
* Created by Janis Hutz 05/31/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
"""

View File

@@ -1,7 +1,5 @@
[PathSettings] [PathSettings]
defaultOutputPath = $HOME/FSRImageVideoUpscaler/ defaultOutputPath = $HOME/FSRSimpleMediaUpscalerLite/
tmpPathLinux = /tmp/
tmpPathWindows = C:\temp
[DevSettings] [DevSettings]
loggerReqLevel = DEBUG loggerReqLevel = DEBUG

View File

@@ -1,4 +1,4 @@
# imagevideoupscaler # SimpleMediaUpscalerLite
## Project setup ## Project setup
``` ```

BIN
frontend/logo.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,20 @@
{ {
"name": "imagevideoupscaler", "name": "SimpleMediaUpscalerLite",
"version": "0.1.0", "version": "2.0.0",
"maintainers": [
"Janis Hutz <development@janishutz.com>"
],
"description": "An Electron frontend to the SimpleMediaUpscalerLite-CLI",
"homepage": "https://janishutz.com/scaler.html",
"author": {
"name": "Janis Hutz",
"email": "development@janishutz.com",
"url": "https://janishutz.com"
},
"license": "GPL-3.0-or-later",
"bugs": {
"url": "https://github.com/simplePCBuilding/SimpleMediaUpscalerLite/issues"
},
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
@@ -13,8 +27,9 @@
}, },
"main": "background.js", "main": "background.js",
"dependencies": { "dependencies": {
"child_process": "^1.0.2",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"electron": "^24.3.1", "electron-squirrel-startup": "^1.0.0",
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3" "vue-router": "^4.0.3"
}, },
@@ -25,6 +40,7 @@
"@vue/cli-plugin-eslint": "~5.0.0", "@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-router": "~5.0.0", "@vue/cli-plugin-router": "~5.0.0",
"@vue/cli-service": "~5.0.0", "@vue/cli-service": "~5.0.0",
"electron": "^24.4.1",
"electron-devtools-installer": "^3.1.0", "electron-devtools-installer": "^3.1.0",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.0.3",

View File

View File

View File

View File

@@ -2,6 +2,8 @@
<nav> <nav>
<router-link to="/">Home</router-link> | <router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> <router-link to="/about">About</router-link>
<!-- |
<router-link to="/settings">Settings</router-link> -->
</nav> </nav>
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition || 'scale'" mode="out-in"> <transition :name="route.meta.transition || 'scale'" mode="out-in">
@@ -49,13 +51,17 @@ export default {
<style> <style>
:root, :root.light { :root, :root.light {
--background-color: rgb(224, 222, 222); --background-color: rgb(224, 222, 222);
--dialog-color: rgb(243, 241, 241);
--foreground-color: #2c3e50; --foreground-color: #2c3e50;
--highlight-color: rgb(221, 0, 0); --highlight-color: rgb(221, 0, 0);
--input-color: rgb(150, 150, 150);
} }
:root.dark { :root.dark {
--background-color: rgb(34, 34, 34); --background-color: rgb(34, 34, 34);
--foreground-color: white; --foreground-color: white;
--dialog-color: rgb(51, 51, 51);
--input-color: rgb(121, 121, 121);
} }
body, html { body, html {

40
frontend/src/app.js Normal file
View File

@@ -0,0 +1,40 @@
module.exports = function ( win ) {
const dialog = require( 'electron' ).dialog;
const upscaling = require( './upscalingHandler.js' );
const upscalingHandler = new upscaling();
const ipcMain = require( 'electron' ).ipcMain;
ipcMain.on( 'selectInputFile', ( event, data ) => {
event.reply( 'selectInputFile', { 'data': dialog.showOpenDialogSync( {
properties: [ 'openFile' ],
title: 'Select an input file to upscale',
filters: [
{ name: 'Images (.jpg, .png)', extensions: ['jpg', 'png'] },
{ name: 'Movies (.mkv, .mp4)', extensions: ['mkv', 'mp4'] },
{ name: 'All Files', extensions: ['*'] }
]
} ) } );
} );
ipcMain.on( 'selectOutputFile', ( event, data ) => {
event.reply( 'selectOutputFile', { 'data': dialog.showSaveDialogSync( {
properties: [ 'promptToCreate' ],
title: 'Select an output file',
filters: [
{ name: 'Images (.jpg, .png)', extensions: ['jpg', 'png'] },
{ name: 'Movies (.mkv, .mp4)', extensions: ['mkv', 'mp4'] },
{ name: 'All Files', extensions: ['*'] }
]
} ) } );
} );
ipcMain.on( 'startUpscaling', ( event, data ) => {
let checks = upscalingHandler.verifyDataIntegrity( JSON.parse( data ), ipcMain );
if ( checks[ 0 ] ) {
event.reply( 'startUpscaling', { 'data': checks[ 1 ] } );
upscalingHandler.upscale( JSON.parse( data ), win );
} else {
event.reply( 'startUpscaling', { 'data': checks[ 1 ] } );
}
} );
}

BIN
frontend/src/assets/logo.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 592 KiB

View File

@@ -1,9 +1,11 @@
'use strict' 'use strict'
import { app, protocol, BrowserWindow } from 'electron' import { app, protocol, BrowserWindow } from 'electron';
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib';
import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer' import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer';
const isDevelopment = process.env.NODE_ENV !== 'production' const isDevelopment = process.env.NODE_ENV !== 'production';
const path = require( 'path' );
// Scheme must be registered before the app is ready // Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([ protocol.registerSchemesAsPrivileged([
@@ -20,10 +22,10 @@ async function createWindow() {
// Use pluginOptions.nodeIntegration, leave this alone // Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
} }
}) })
if (process.env.WEBPACK_DEV_SERVER_URL) { if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode // Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
@@ -33,6 +35,7 @@ async function createWindow() {
// Load the index.html when not in development // Load the index.html when not in development
win.loadURL('app://./index.html') win.loadURL('app://./index.html')
} }
require( './app.js' )( win );
} }
// Quit when all windows are closed. // Quit when all windows are closed.

View File

@@ -10,10 +10,12 @@ const routes = [
{ {
path: '/about', path: '/about',
name: 'about', name: 'about',
// route level code-splitting component: () => import( '../views/AboutView.vue' )
// this generates a separate chunk (about.[hash].js) for this route },
// which is lazy-loaded when the route is visited. {
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue') path: '/settings',
name: 'settings',
component: () => import( '../views/SettingsView.vue' )
} }
] ]

View File

@@ -0,0 +1,92 @@
/*
* SimpleMediaUpscalerLite - upscalingHandler.js
*
* Created by Janis Hutz 06/03/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com
*
*
*/
const child_process = require( 'child_process' );
const process = require( 'process' );
const Notification = require( 'electron' ).Notification;
class UpscalingHandler {
constructor () {
this.os = process.platform
}
upscale( options, win ) {
// required options: engine, algorithm, scale, sharpening, InputFile & OutputFile
// Options is an object!
let baseCommand = '';
// Create cli command to upscale
if ( this.os === 'linux' ) {
baseCommand = './smuL-cli';
} else if ( this.os === 'win32' ) {
baseCommand = 'smuL-cli.exe';
}
let args = []
args.push( '-i' + options.InputFile );
args.push( '-o' + options.OutputFile );
if ( options.scale != 0 ) {
args.push( '-s' + options.scale );
}
if ( options.sharpening != 0 ) {
args.push( '-S' + options.sharpening );
}
args.push( '-M' + options.algorithm );
args.push( '-E' + options.engine );
// add additional options
// baseCommand += + ' -S ' + options.sharpening
// baseCommand += ' -E ' + options.engine + ' -M ' + options.algorithm
console.log( 'upscaling' );
console.log( args );
let child = child_process.spawn( baseCommand, args );
child.stdout.on( 'data', data => {
console.log( '' + data );
win.send( 'progress', '\n' + data );
} );
child.stderr.on( 'data', ( data ) => {
console.error(`stderr: ${ data }`);
win.send( 'progress', '\n' + data );
} );
child.on( 'error', ( error ) => {
console.log( 'An error occurred' + error );
win.send( 'error', 'An error occurred during upscaling. (Error message: ' + error.message + ')' );
new Notification( { title: `SimpleMediaUpscalerLite - Error whilst upscaling', body: 'Your upscaling Job encountered an error whilst upscaling. (Error message: ${ error.message }).`} ).show();
} );
child.on( 'close', ( code ) => {
win.send( 'finish', 'Your upscaling job finished with exit code ' + code + '. You may find its output here: ' + options.OutputFile );
new Notification( { title: `SimpleMediaUpscalerLite - Job complete', body: 'Your Upscaling job has completed successfully (Code ${ code }). You may find its output here: ` + options.OutputFile } ).show();
} );
}
verifyDataIntegrity ( data ) {
if ( data[ 'InputFile' ] && data[ 'OutputFile' ] && data[ 'engine' ] && data[ 'algorithm' ] && 1 < data[ 'scale' ] <= 4 && 0 <= data[ 'sharpening' ] <= 1 ) {
if ( data[ 'InputFile' ][ 0 ].substring( data[ 'InputFile' ][ 0 ].length - 4 ) == data[ 'OutputFile' ].substring( data[ 'OutputFile' ].length - 4 ) ) {
return [ true, 'upscaling' ];
} else {
return [ false, 'differentFileExtensions' ];
}
} else {
return [ false, 'dataMissing' ];
};
}
}
module.exports = UpscalingHandler;

View File

@@ -1,22 +1,10 @@
<template> <template>
<div class="about"> <div class="about">
<img src="@/assets/logo.png"> <img src="@/assets/logo.png" style="height: 30vh;">
<h1>About ImageVideoUpscaler</h1> <h1>About SimpleMediaUpscalerLite</h1>
<p>ImageVideoUpscaler is an application that allows you to upscale your videos and / or images. It uses an Electron GUI (Graphical User Interface) and a Python CLI (Command Line Interface).</p> <p>SimpleMediaUpscalerLite is an application that allows you to upscale your videos and / or images. It uses an Electron GUI (Graphical User Interface) and a Python CLI (Command Line Interface).</p>
<h3>Contributors</h3>
<ul>
<li>Janis Hutz (simplePCBuilding): Maintainer, CLI & GUI development, Packaging</li>
<li>ThatPlasma: App name, Logo, testing, Windows installer</li>
</ul>
<div class="version-info"> <div class="version-info">
<h3>You are currently running version 1.1.0</h3> <h3>You are currently running version {{ appVersion }}. {{ versionNotice[ isUpToDate ] }}.</h3>
<h3>Changelog</h3>
<ul>
<li>
Version 1.0
<ul></ul>
</li>
</ul>
</div> </div>
</div> </div>
</template> </template>
@@ -25,14 +13,21 @@
export default { export default {
data() { data() {
return { return {
version: '', versionNotice: { true: '==> up to date', false: '==> New version available' },
appVersion: 'V2.0.0',
latestVersion: '',
isUpToDate: true, isUpToDate: true,
} }
}, },
mounted () { mounted () {
fetch( 'https://github.com/simplePCBuilding/ImageVideoUpscaler/blob/master/package.json' ).then( res => { fetch( 'https://api.github.com/repos/simplePCBuilding/SimpleMediaUpscalerLite/releases/latest' ).then( res => {
console.log( res ); res.json().then( data => {
}) this.latestVersion = data.tag_name;
if ( data.tag_name != this.appVersion ) {
this.isUpToDate = false;
}
} );
} );
} }
} }
</script> </script>

View File

@@ -1,11 +1,308 @@
<template> <template>
<div class="home"> <div class="home">
<h1>ImageVideoUpscaler</h1> <h1>SimpleMediaUpscalerLite</h1>
<div class="table-container">
<table>
<tr id="group1" class="group">
<td>
<label for="algorithm">Upscaler engine</label><br>
<select name="engine" id="engine" v-model="upscaleSettings.engine">
<option v-for="engine in engines" :key="engine.id" :value="engine.id">{{ engine.displayName }}</option>
</select><br>
</td>
<td>
<label for="algorithm">Upscaling algorithm</label><br>
<select name="algorithm" id="algorithm" v-model="upscaleSettings.algorithm">
<option v-for="engine in engines[ upscaleSettings.engine ][ 'modes' ]" :key="engine.id" :value="engine.id">{{ engine.displayName }}</option>
</select><br>
</td>
</tr>
<tr id="group2" class="group">
<td v-if="engines[ upscaleSettings.engine ][ 'supports' ].includes( 'upscaling' )">
<label for="scale">Scale factor</label><br>
<input type="number" name="scale" id="scale" v-model="upscaleSettings.scale" min="2" max="4" onkeydown="return false">x<br>
</td>
<td v-if="engines[ upscaleSettings.engine ][ 'supports' ].includes( 'sharpening' )">
<label for="sharpening">Sharpening factor</label><br>
<input type="number" step="0.01" name="scale" id="scale" v-model="upscaleSettings.sharpening" min="0" max="1"><br>
</td>
</tr>
<tr id="group3" class="group">
<td>
<button @click="runCommand( 'InputFile' )">Input file</button><br>
<div v-if="upscaleSettings.InputFile[ 0 ]" id="inputCheck" @mouseenter="showElement( 'inputfile' )" @mouseleave="hideElement( 'inputfile' )">&#10004;</div>
<div class="info-container">
<div class="info" id="inputfile">
{{ upscaleSettings.InputFile[ 0 ] }}
</div>
</div>
</td>
<td>
<button @click="runCommand( 'OutputFile' )">Output file</button><br>
<div v-if="upscaleSettings.OutputFile" id="outputCheck" @mouseenter="showElement( 'outputfile' )" @mouseleave="hideElement( 'outputfile' )">&#10004;</div>
<div class="info-container">
<div class="info" id="outputfile">
{{ upscaleSettings.OutputFile }}
</div>
</div>
</td>
</tr>
</table>
<button @click="start()" id="start">Start upscaling</button>
</div>
<div class="output-box-wrapper">
<p id="cmd" @click="showCmdOutput()">Command output</p>
<div class="output-box" id="output" v-html="output">
</div>
</div>
<dialog id="processing">
<div class="dialog-container">
Your file is being processed. You will be notified when the upscaling process has finished.
<form method="dialog">
<button>OK</button>
</form>
</div>
</dialog>
<dialog id="wrong">
<div class="dialog-container">
Some entries are missing. Please ensure that you have specified an input file!
<form method="dialog">
<button>OK</button>
</form>
</div>
</dialog>
<dialog id="completed">
<div class="dialog-container">
<p style="width: 90%; word-wrap: break-word;">{{ finishMessage }}</p>
<form method="dialog">
<button>OK</button>
</form>
</div>
</dialog>
<dialog id="error">
<div class="dialog-container">
<p style="width: 90%; word-wrap: break-word;">{{ errorMessage }}</p>
<form method="dialog">
<button>OK</button>
</form>
</div>
</dialog>
<dialog id="fileExtension">
<div class="dialog-container">
File extension of input and output file don't match! Please ensure that they are the same.
Click the button below to fix it.
<button @click="fixFileExtension();">Fix</button>
<p v-if="fixed">Fixed!</p>
<form method="dialog">
<button @click="this.fixed = false;">OK</button>
</form>
</div>
</dialog>
</div> </div>
</template> </template>
<script> <script>
import { ipcRenderer } from 'electron';
export default { export default {
name: 'HomeView', name: 'HomeView',
data() {
return {
upscaleSettings: { 'engine': 'ffc', 'algorithm': 'fsr', 'scale': 2, 'sharpening': 0, 'InputFile': [], 'OutputFile': '' },
engines: { 'ffc':{ 'displayName': 'FidelityFX CLI', 'id': 'ffc', 'modes': { 'fsr': { 'displayName': 'FidelityFX Super Resolution', 'id': 'fsr' }, 'c': { 'displayName': 'Cubic', 'id': 'c' }, 'hqc': { 'displayName': 'High Quality Cubic', 'id': 'hqc' } }, 'supports': [ 'upscaling', 'sharpening' ] }, 'ss':{ 'displayName': 'REAL-ESRGAN', 'id': 'ss', 'modes': { 'av3': { 'displayName': 'realesr-animevideov3', 'id': 'av3' }, 'x4plus': { 'displayName': 'realesrgan-x4plus-anime', 'id': 'x4plus' } }, 'supports': [ 'upscaling' ] } },
fixed: false,
output: '',
finishMessage: '',
errorMessage: '',
}
},
methods: {
runCommand ( command ) {
ipcRenderer.send( 'select' + command );
ipcRenderer.on( 'select' + command, ( event, data ) => {
if ( command == 'InputFile' ) {
this.upscaleSettings[ 'OutputFile' ] = data[ 'data' ][ 0 ].substring( 0, data[ 'data' ][ 0 ].length - 4 ) + '_upscaled' + data[ 'data' ][ 0 ].substring( data[ 'data' ][ 0 ].length - 4 );
}
this.upscaleSettings[ command ] = data[ 'data' ];
} );
},
start() {
this.output = '';
ipcRenderer.send( 'startUpscaling', JSON.stringify ( this.upscaleSettings ) );
ipcRenderer.on( 'startUpscaling', ( event, data ) => {
if ( data.data == 'upscaling' ) {
try {
document.getElementById( 'processing' ).showModal();
} catch ( error ) {
console.log( error );
}
} else if ( data.data == 'dataMissing' ) {
document.getElementById( 'wrong' ).showModal();
} else {
document.getElementById( 'fileExtension' ).showModal();
}
} );
let self = this;
ipcRenderer.on( 'progress', function ( evt, message ) {
self.output = message + self.output;
});
ipcRenderer.on( 'finish', function ( evt, message ) {
if ( self.errorMessage == '' ) {
self.finishMessage = message;
try {
document.getElementById( 'processing' ).close();
document.getElementById( 'completed' ).showModal();
} catch ( error ) {
console.log( error );
}
}
} )
ipcRenderer.on( 'error', function ( evt, message ) {
self.errorMessage = message;
try {
document.getElementById( 'processing' ).close();
document.getElementById( 'error' ).showModal();
} catch ( error ) {
console.log( error );
}
} )
},
showCmdOutput () {
document.getElementById( 'output' ).classList.toggle( 'shown' );
},
fixFileExtension () {
let fileExtension = this.upscaleSettings.InputFile[ 0 ].substring( this.upscaleSettings.InputFile[ 0 ].length - 4 );
this.upscaleSettings.OutputFile = this.upscaleSettings.OutputFile.slice( 0, this.upscaleSettings.OutputFile[ 0 ].length - 5 ) + fileExtension;
this.fixed = true;
},
showElement( element ) {
document.getElementById( element ).classList.add( 'shown' );
},
hideElement( element ) {
document.getElementById( element ).classList.remove( 'shown' );
}
},
} }
</script> </script>
<style scoped>
.info-container {
position: relative;
}
.info {
display: none;
position: absolute;
background-color: var( --dialog-color );
padding: 2vw;
width: 20vw;
height: 20vh;
word-wrap: break-word;
}
.shown {
display: block;
}
.table-container {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
table {
border-spacing: 3vw 0;
}
#start {
margin-top: 5vh;
padding: 1vw 2vw;
margin-bottom: 0;
cursor: pointer;
}
button {
background-color: var( --input-color );
margin-top: 1vw;
padding: 0.5vw 1vw;
border-radius: 20px;
border-style: none;
cursor: pointer;
transition: all 0.4s;
}
button:hover {
background-color: #42b983;
}
input, select {
background-color: var( --input-color );
margin-bottom: 1vw;
margin-top: 0.3vw;
padding: 0.5vw 1vw;
border-radius: 20px;
}
.output-box-wrapper {
margin-top: 3%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.output-box {
display: none;
overflow-y: scroll;
overflow-x: hidden;
word-wrap: normal;
height: 20vh;
width: 60%;
text-align: justify;
white-space: pre-line;
}
.shown {
display: block;
}
dialog {
border-radius: 10px;
height: 30vh;
width: 30vw;
background-color: var( --background-color );
border-style: none;
color: var( --primary-color );
}
.dialog-container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#cmd {
text-align: justify;
width: 60%;
cursor: pointer;
user-select: none;
}
</style>

View File

@@ -0,0 +1,30 @@
<template>
<div class="about">
<h1>Settings</h1>
<p>WIP!</p>
</div>
</template>
<script>
export default {
data() {
return {
engines: '',
}
},
methods: {
run() {
fetch( 'http://127.0.0.1:49369/api/getEngines' ).then( res => {
console.log( res );
res.json().then( data => {
this.engines = data.body;
} );
} ).catch( error => {
console.log( error );
} );
}
},
created() {
}
}
</script>

View File

@@ -1,4 +1,27 @@
const { defineConfig } = require('@vue/cli-service') module.exports = {
module.exports = defineConfig({ pluginOptions: {
transpileDependencies: true electronBuilder: {
}) nodeIntegration: true,
"appId": "com.janishutz.smuL",
"copyright": "Copyright (c) 2023 SimpleMediaUpscalerLite contributors",
"buildVersion": "V2.0.0-dev2",
builderOptions: {
files: [
"**/*",
{
from: "./*",
to: "./*",
filter: [ "**/*" ]
}
],
extraFiles: [
{
from: "./lib",
to: "./",
filter: [ "**/*" ]
}
]
}
}
}
}

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 592 KiB

View File

@@ -1,6 +1,6 @@
{ {
"name": "imagevideoupscaler", "name": "SimpleMediaUpscalerLite",
"version": "1.0.0", "version": "2.0.0",
"description": "A frontend to upscale your videos and images using different upscale engines", "description": "A frontend to upscale your videos and images using different upscale engines",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -8,7 +8,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/simplePCBuilding/FSRImageVideoUpscalerFrontend.git" "url": "git+https://github.com/simplePCBuilding/SimpleMediaUpscalerLite.git"
}, },
"keywords": [ "keywords": [
"upscaler", "upscaler",
@@ -21,7 +21,8 @@
"author": "Janis Hutz", "author": "Janis Hutz",
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"bugs": { "bugs": {
"url": "https://github.com/simplePCBuilding/FSRImageVideoUpscalerFrontend/issues" "url": "https://github.com/simplePCBuilding/SimpleMediaUpscalerLite/issues",
"email": "development@janishutz.com"
}, },
"homepage": "https://github.com/simplePCBuilding/FSRImageVideoUpscalerFrontend#readme" "homepage": "https://github.com/simplePCBuilding/SimpleMediaUpscalerLite#readme"
} }

View File

@@ -1,7 +0,0 @@
[Desktop Entry]
Type=Application
Name=FSR Image & Video Upscaler
Comment=Upscale your videos and images with FSR
Path=/opt/fsrimageupscaler
Exec=/opt/fsrimageupscaler/FSR\ Image\ \&\ Video\ Upscaler
Icon=fsrimageupscaler

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

60
packaging/package.sh Normal file → Executable file
View File

@@ -2,17 +2,53 @@
cd .. cd ..
# Make linux executable # Compile for Linux
pyinstaller imagevideoupscaler-cli.spec python -m PyInstaller smuL-cli.spec
mv -r ./dist/imagevideupscaler ./dist/imagevideupscaler-linux
cp -r ./bin ./dist/imagevideupscaler-linux
cp -r ./config ./dist/imagevideupscaler-linux
cp ./imagevideupscaler-cli.py ./dist/imagevideupscaler-linux
cp ./LICENSE ./dist/imagevideupscaler-linux
cp ./logo.png ./dist/imagevideupscaler-linux
# package rpm & deb mkdir ./frontend/lib/
# TODO: create packager cp -rv ./dist/smuL-cli/* ./frontend/lib/
# Make windows executable
# TODO: create compiler # Copy python files
cp -rv ./bin ./frontend/lib/
cp -rv ./config ./frontend/lib/
cp -v ./smuL-cli.py ./frontend/lib/
cp -v ./LICENSE ./frontend/lib/
cp -v ./logo.png ./frontend/lib/
# package for Linux (includes GUI & CLI)
cd frontend
rm -rf ./dist_electron
npm run electron:build -- --linux deb rpm
rm -rf ./lib/libdynload
rm ./lib/smuL*
rm ./lib/lib*
rm ./lib/ld*
rm ./lib/base_library.zip
cd ..
rm -rf ./build
rm -rf ./dist
printf '\n\n==> Finished Linux packaging, preparing Windows\n\n'
# Compile for Windows
wine python -m PyInstaller smuL-cli.spec
cp -rv ./dist/smuL-cli/* ./frontend/lib/
cp -v ./smuL-cli.py ./frontend/lib/
# package for Windows (includes GUI & CLI)
cd frontend
npm run electron:build -- --win nsis
rm -rf ./lib
cd ..
rm -rf ./build
rm -rf ./dist
printf '\n\n==> DONE\n\n'

30
packaging/packageLinux.sh Executable file
View File

@@ -0,0 +1,30 @@
#! /bin/bash
cd ..
# Compile for Linux
python -m PyInstaller smuL-cli.spec
cp -r ./dist/smuL-cli/* ./frontend/lib/
# Copy python files
cp -r ./bin ./frontend/lib/
cp -r ./config ./frontend/lib/
cp ./smuL-cli.py ./frontend/lib/
cp ./LICENSE ./frontend/lib/
cp ./logo.png ./frontend/lib/
# package for Linux (includes GUI & CLI)
cd frontend
rm -rf ./dist_electron
npm run electron:build -- --linux deb rpm
rm -rf ./lib
cd ..
rm -rf ./build
rm -rf ./dist
printf '\n\n==> DONE\n\n'

31
packaging/packageTesting.sh Executable file
View File

@@ -0,0 +1,31 @@
#! /bin/bash
cd ..
# Compile for Linux
python -m PyInstaller smuL-cli.spec
mkdir ./frontend/lib
cp -r ./dist/smuL-cli/* ./frontend/lib/
# Copy python files
cp -r ./bin ./frontend/lib/
cp -r ./config ./frontend/lib/
cp ./smuL-cli.py ./frontend/lib/
cp ./LICENSE ./frontend/lib/
cp ./logo.png ./frontend/lib/
# package for Linux (includes GUI & CLI)
cd frontend
rm -rf ./dist_electron
npm run electron:build -- --linux zip
rm -rf ./lib
cd ..
rm -rf ./build
rm -rf ./dist
printf '\n\n==> DONE\n\n'

31
packaging/packageWindows.sh Executable file
View File

@@ -0,0 +1,31 @@
#! /bin/bash
cd ..
# Compile for Windows
wine python -m PyInstaller smuL-cli.spec
mkdir ./frontend/lib
cp -r ./dist/smuL-cli/* ./frontend/lib/
# Copy python files
cp -rv ./bin ./frontend/lib/
cp -rv ./config ./frontend/lib/
cp -v ./smuL-cli.py ./frontend/lib/
cp -v ./LICENSE ./frontend/lib/
cp -v ./logo.png ./frontend/lib/
# package for Windows (includes GUI & CLI)
cd frontend
rm -rf ./dist_electron
npm run electron:build -- --win nsis
rm -rf ./lib
cd ..
rm -rf ./build
rm -rf ./dist
printf '\n\n==> DONE\n\n'

6
packaging/prepareWindowsPackaging.sh Normal file → Executable file
View File

@@ -1,5 +1,7 @@
curl -o ./pythonInstaller.exe https://www.python.org/ftp/python/3.10.11/python-3.10.11-amd64.exe curl -o ./pythonInstaller.exe https://www.python.org/ftp/python/3.11.3/python-3.11.3-amd64.exe
wine pythonInstaller.exe wine pythonInstaller.exe
currentPath = pwd wine python -m pip install pyinstaller
printf '\n\n==> Done installing python for windows\n\n'

15
packaging/startTesting.sh Executable file
View File

@@ -0,0 +1,15 @@
#! /bin/bash
cd ..
# Compile for Linux
python -m PyInstaller smuL-cli.spec
cp -r ./dist/smuL-cli/* ./frontend/
# Copy python files
cp -r ./bin ./frontend/
cp -r ./config ./frontend/
cp ./smuL-cli.py ./frontend/
cp ./LICENSE ./frontend/
cp ./logo.png ./frontend/

21
packaging/stopTesting.sh Executable file
View File

@@ -0,0 +1,21 @@
#! /bin/bash
cd ../frontend
rm -rf ./bin
rm -rf ./config
rm -rf ./lib-dynload
rm -rf ./libdynload
rm ./smuL*
rm ./lib*
rm ./ld*
rm ./base_library.zip
rm ./LICENSE
rm ./_*
rm ./*.dll
rm ./*.pyd
cd ..
rm -rf ./build
rm -rf ./dist

3
plugins/plugins.json Normal file
View File

@@ -0,0 +1,3 @@
{
"fsr": { "displayName":"AMD FidelityFX Super Resolution" }
}

View File

@@ -1,5 +1,5 @@
""" """
* FSRImageVideoUpscalerFrontend - fsrimagevideoupscaler-cli.py * SimpleMediaUpscalerLite - fsrSimpleMediaUpscalerLite-cli.py
* *
* Created by Janis Hutz 03/15/2023, Licensed under the GPL V3 License * Created by Janis Hutz 03/15/2023, Licensed under the GPL V3 License
* https://janishutz.com, development@janishutz.com * https://janishutz.com, development@janishutz.com
@@ -14,7 +14,11 @@ import multiprocessing
import json import json
engineList = os.listdir( 'bin/engines' ); engineList = os.listdir( 'bin/engines' );
engineList.pop( 0 ) counter = 0;
for element in engineList:
if ( element == '__pycache__' ):
engineList.pop( counter );
counter += 1;
engineInfo = {} engineInfo = {}
@@ -28,16 +32,20 @@ def performChecks ( args, ap ):
if ( not args.printengines ): if ( not args.printengines ):
if ( not args.version ): if ( not args.version ):
# Check if input and output file arguments are available # Check if input and output file arguments are available
if ( args.inputfile == None or args.inputfile == '' or args.outputfile == None or args.outputfile == '' ): if ( args.inputfile == None or args.inputfile == '' ):
print( '\n\n ==> ERROR: Input and output file required! <==\n\n' ) print( '\n\n ==> ERROR: Input file required! <==\n\n' )
ap.print_usage(); ap.print_usage();
return False return False
output = args.outputfile;
if ( args.outputfile == None or args.outputfile == '' ):
output = args.inputfile[ :len( args.inputfile ) - 4 ] + '_upscaled' + args.inputfile[ len( args.inputfile ) - 4: ]
# check if output file exists and if, prompt user if it should be overwritten and remove if, if yes # check if output file exists and if, prompt user if it should be overwritten and remove if, if yes
if ( os.path.exists( args.outputfile ) ): if ( os.path.exists( output ) and ( args.overwrite == None or args.overwrite == '' ) ):
doReplace = input( '--> File already exists. Do you want to replace it? (Y/n) ' ).lower() doReplace = input( '--> File already exists. Do you want to replace it? (Y/n) ' ).lower()
if ( doReplace == 'y' or doReplace == '' ): if ( doReplace == 'y' or doReplace == '' ):
os.remove( args.outputfile ); os.remove( output );
else: else:
print( '\n==> Refusing to Upscale video. Please delete the file or specify another filepath! <==' ) print( '\n==> Refusing to Upscale video. Please delete the file or specify another filepath! <==' )
return False return False
@@ -46,7 +54,9 @@ def performChecks ( args, ap ):
try: try:
engineInfo[ args.engine.lower() ] engineInfo[ args.engine.lower() ]
except KeyError: except KeyError:
print( '\n==> ERROR: Engine not available. Ensure you have specified a valid engine' ) print( '\n==> ERROR: Engine ' + args.engine.lower() + ' not available. Ensure you have specified a valid engine. Possible engines: ' )
for entry in engineList:
print( ' --> ' + entry )
return False return False
# Check scalefactor argument and also verify that engine supports upscaling # Check scalefactor argument and also verify that engine supports upscaling
@@ -60,9 +70,9 @@ def performChecks ( args, ap ):
return False return False
# Check sharpening argument and also verify that engine supports it # Check sharpening argument and also verify that engine supports it
if ( args.sharpening != None and args.sharpening != 0 ): if ( args.sharpening != None and args.sharpening != 0 ):
if ( float( args.sharpening ) >= 1 and float( args.sharpening ) <= 0 ): if ( float( args.sharpening ) >= 1.0 or float( args.sharpening ) <= 0.0 ):
print( '\n==> ERROR: Invalid value for sharpening. Value has to be between 0 and 1' ) print( '\n==> ERROR: Invalid value (' + args.sharpening + ') for sharpening. Value has to be between 0 and 1' )
return False return False
else: else:
if ( not 'sharpening' in engineInfo[ args.engine ][ 'supports' ] ): if ( not 'sharpening' in engineInfo[ args.engine ][ 'supports' ] ):
@@ -95,9 +105,14 @@ def performChecks ( args, ap ):
else: else:
print( '\n\n==> Available engines <==\n' ) print( '\n\n==> Available engines <==\n' )
for entry in engineList: for entry in engineList:
print( '--> ' + entry ) print( ' --> ' + entry )
print( '\n\n' ) print( '\n\n' )
else: else:
try:
engineInfo[ args.details.lower() ]
except KeyError:
print( '\n\n ==> That engine does not exist. Please use the -p option to check for available engines!\n\n' )
return False
print( '\n\n ==> INFOS about ' + engineInfo[ args.details.lower() ][ 'displayName' ] + '\n' ) print( '\n\n ==> INFOS about ' + engineInfo[ args.details.lower() ][ 'displayName' ] + '\n' )
print( ' --> Engine cli option is: ' + engineInfo[ args.details ][ 'abbr' ].lower() ) print( ' --> Engine cli option is: ' + engineInfo[ args.details ][ 'abbr' ].lower() )
print( ' --> CLI mode options are: ' ) print( ' --> CLI mode options are: ' )
@@ -108,7 +123,7 @@ def performChecks ( args, ap ):
print( '\n\n' ) print( '\n\n' )
if __name__ == '__main__': if __name__ == '__main__':
ap = argparse.ArgumentParser( description='ImageVideoUpscaler - CLI, a CLI application to upscale videos and images using different upscaling engines.' ) ap = argparse.ArgumentParser( description='SimpleMediaUpscalerLite - CLI, a CLI application to upscale videos and images using different upscaling engines.' )
ap.add_argument( '-i', '--inputfile', help='File path for the video / image to be upscaled' ) ap.add_argument( '-i', '--inputfile', help='File path for the video / image to be upscaled' )
ap.add_argument( '-o', '--outputfile', help='Output file path for the video / image that was upscaled' ) ap.add_argument( '-o', '--outputfile', help='Output file path for the video / image that was upscaled' )
ap.add_argument( '-s', '--scalefactor', help='Scale factor for the video / image. Can be a integer from -4 to 4' ) ap.add_argument( '-s', '--scalefactor', help='Scale factor for the video / image. Can be a integer from -4 to 4' )
@@ -118,9 +133,10 @@ if __name__ == '__main__':
ap.add_argument( '-M', '--mode', help='Specify a special mode for a specific engine. Might not be available in every engine. Use the -d option to find out more' ) ap.add_argument( '-M', '--mode', help='Specify a special mode for a specific engine. Might not be available in every engine. Use the -d option to find out more' )
ap.add_argument( '-F', '--filetype', help='Change the file type of the temporary image files. Supports png, jpg. Video quality: png > jpg. PNG is default, if not specified.' ) ap.add_argument( '-F', '--filetype', help='Change the file type of the temporary image files. Supports png, jpg. Video quality: png > jpg. PNG is default, if not specified.' )
ap.add_argument( '-d', '--details', help='Get details on usage of a particular engine and exit. Reads the config.json file of that engine and displays it in a HR manner' ) ap.add_argument( '-d', '--details', help='Get details on usage of a particular engine and exit. Reads the config.json file of that engine and displays it in a HR manner' )
ap.add_argument( '-y', '--overwrite', help='Always overwrite output path and do not ask', action='store_true' )
ap.add_argument( '-p', '--printengines', help='Print all engines and exit', action='store_true' ) ap.add_argument( '-p', '--printengines', help='Print all engines and exit', action='store_true' )
ap.add_argument( '-v', '--version', help='Print version and exit', action='store_true' ) ap.add_argument( '-v', '--version', help='Print version and exit', action='store_true' )
ap.set_defaults( scaling = 0, sharpening = 0, threads = 4, engine = 'fsr', filetype = 'png' ) ap.set_defaults( scalefactor = 0, sharpening = 0, threads = 4, engine = 'ffc', filetype = 'png' )
args = ap.parse_args() args = ap.parse_args()
handler = bin.handler.Handler() handler = bin.handler.Handler()
@@ -128,6 +144,10 @@ if __name__ == '__main__':
multiprocessing.freeze_support(); multiprocessing.freeze_support();
if ( performChecks( args, ap ) ): if ( performChecks( args, ap ) ):
output = args.outputfile;
if ( args.outputfile == None or args.outputfile == '' ):
output = args.inputfile[ :len( args.inputfile ) - 4 ] + '_upscaled' + args.inputfile[ len( args.inputfile ) - 4: ]
mode = 'fsr' mode = 'fsr'
if ( args.mode != None ): if ( args.mode != None ):
mode = args.mode mode = args.mode
@@ -136,7 +156,8 @@ if __name__ == '__main__':
if ( engineInfo[ args.engine ][ 'cliModeOptions' ][ option ][ 'default' ] ): if ( engineInfo[ args.engine ][ 'cliModeOptions' ][ option ][ 'default' ] ):
mode = option mode = option
break break
handler.handler( args.inputfile, args.scalefactor, args.outputfile, args.sharpening, args.filetype, args.engine, mode, args.threads )
print( '\n\n---------------------------------------------------------------------------------\n\nDONE \n\n\n\nImageVideoUpscalerFrontend V1.1.0\n\nCopyright 2023 FSRImageVideoUpscalerFrontend contributors\nThis application comes with absolutely no warranty to the extent permitted by applicable law\n\n\n\nOutput was written to ' + args.outputfile + '\n\n\n' )
if ( handler.handler( args.inputfile, args.scalefactor, output, args.sharpening, args.filetype, args.engine, mode, args.threads ) ):
print( '\n\n---------------------------------------------------------------------------------\n\nDONE \n\n\n\nSimpleMediaUpscalerLite V1.1.0\n\nCopyright 2023 SimpleMediaUpscalerLite contributors\nThis application comes with absolutely no warranty to the extent permitted by applicable law\n\n\n\nOutput was written to ' + output + '\n\n\n' )
else:
raise Exception( 'ERRORS in arguments' );

View File

@@ -5,7 +5,7 @@ block_cipher = None
a = Analysis( a = Analysis(
['imagevideoupscaler-cli.py'], ['smuL-cli.py'],
pathex=[], pathex=[],
binaries=[], binaries=[],
datas=[], datas=[],
@@ -26,7 +26,7 @@ exe = EXE(
a.scripts, a.scripts,
[], [],
exclude_binaries=True, exclude_binaries=True,
name='imagevideoupscaler', name='smuL-cli',
debug=False, debug=False,
bootloader_ignore_signals=False, bootloader_ignore_signals=False,
strip=False, strip=False,
@@ -46,5 +46,5 @@ coll = COLLECT(
strip=False, strip=False,
upx=True, upx=True,
upx_exclude=[], upx_exclude=[],
name='imagevideoupscaler', name='smuL-cli',
) )

1
website/cropSymbol.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path fill="#FFFFFF" d="M695-40v-165H265q-24 0-42-18t-18-42v-430H40v-60h165v-165h60v655h655v60H755v165h-60Zm0-285v-370H325v-60h370q24 0 42 18t18 42v370h-60Z"/></svg>

After

Width:  |  Height:  |  Size: 254 B

BIN
website/logo.xcf Normal file

Binary file not shown.

View File

@@ -1,4 +1,4 @@
# Writing plugins for ImageVideoUpscaler # Writing plugins for SimpleMediaUpscalerLite
Your plugin has to fulfill the following requirements: Your plugin has to fulfill the following requirements:
- Name of class it exposes has to be [name of engine]Scaler. The name of the file should be just the name of the engine in all lower case. - Name of class it exposes has to be [name of engine]Scaler. The name of the file should be just the name of the engine in all lower case.