#
Comparison
Quality comparisons are frequently used within the enthusiast community to compare the video quality offered by different sources/releases. It serves as a great way to distinguish the differences between good and bad sources, and can help you determine which one to download.
This guide goes through the process of setting up and effectively utilizing VSPreview, a previewer utility for VapourSynth, to produce useful quality comparisons that will allow you to ascertain which release offers the best visual experience.
#
Setup
#
VapourSynth
VapourSynth is an open-source video processing framework. It handles all of your sources, playback, and filtering options in conjunction with VSPreview.
#
Dependencies
- Python 3.12 - Select
Add python.exe to PATH
during installation - Git
#
Installation
Download and install VapourSynth-x64-RXX.exe
from VapourSynth. During installation, select Install for me only
.
#
VSPreview
VSPreview is a previewer application for scripts created in VapourSynth. It features a simple graphical interface to allow you to use VapourSynth's features (and create comparisons) with ease.
#
Dependencies
In order to create comparisons with VSPreview, you will need to install its necessary dependencies.
LibP2P
,LSMASHSource
,Subtext
, andvs-placebo
can be installed usingvsrepo
from VapourSynth. In your terminal, run the following:vsrepo.py install libp2p lsmas sub placebo
If
vsrepo.py
command doesn't work, make sure Windows is set to open.py
files with Python. You may also need to add it to thePATHEXT
environment variable.awsmfunc
can be installed usingpip
:python -m pip install git+https://github.com/OpusGang/awsmfunc.git
If you're working with Dolby Vision (DV) content, you will need to install additional dependencies.
libdovi
can be installed usingvsrepo
from VapourSynth. In your terminal, run the following:vsrepo.py install dovi_library
#
Installation
Download and install vs-jet
using pip
in your terminal:
python -m pip install vsjet
python -m vsjet latest
Currently, installing vs-preview
directly from PyPI or git is broken. Instead, you have to install it using vs-jet
, which will install all JET packages.
#
Usage
#
Scripting
In order to create a comparison, you will need to create a VapourSynth script. This script outlines the parameters and files which VSPreview will use when generating your comparison.
Create a file called comp.py
. Launch it in your favorite text editor and add sections as desired:
Here's a simple comp.py
script example that does nothing more than loading the videos and previewing them.
Make sure to comment (add ##
to the beginning of the line) and uncomment lines as needed.
## Dependencies: Allows vspreview to run [required; do not remove]
from vstools import vs, core
from vskernels import Hermite, EwaLanczos
from vspreview import set_output
## <Additional dependencies>
## Place any additional dependencies you want to use in your comp here
## <End of additional dependencies>
## File paths: Hold shift and right-click your file, select copy as path, and paste it here
clip1 = core.lsmas.LWLibavSource(r"C:\Paste\File\Path\Here.mkv")
clip2 = core.lsmas.LWLibavSource(r"C:\Paste\File\Path\Here.mkv")
clip3 = core.lsmas.LWLibavSource(r"C:\Paste\File\Path\Here.mkv")
## Source: Name of the source
source1 = "FirstSourceName"
source2 = "SecondSourceName"
source3 = "ThirdSourceName"
## <Additional comp settings>
## Place any additional settings you want to use in your comp here
## <End of additional comp settings>
## Output: Comment/uncomment as needed depending on how many clips you're comparing
set_output(clip1, name=source1)
set_output(clip2, name=source2)
set_output(clip3, name=source3)
#
Frame Rate
Sets the source frame rate (fps) based on fractional input (fpsnum
/fpsden
). For example, fpsnum=24000
and fpsden=1001
forces the clip frame rate to 23.976 fps. This should be used on sources that have different frame rates that don't automatically stay in sync.
If a clip stays in sync without changing during scrubbing, you should note that the specific source has dropped or duplicate frames.
## Frame rate: Change fps to match other sources (needed for when the previewer is unable to automatically keep them in sync)
clip1 = core.std.AssumeFPS(clip1, fpsnum=24000, fpsden=1001)
clip2 = core.std.AssumeFPS(clip2, fpsnum=25000, fpsden=1000)
clip3 = core.std.AssumeFPS(clip3, fpsnum=24000, fpsden=1000)
#
FieldBased
Sets interlaced flagged content that may be progressive as progressive for higher quality chroma upscaling.
## FieldBased: Tags the content as progressive (0); used for progressive content tagged as interlaced
clip1 = core.std.SetFieldBased(clip1, 0)
clip2 = core.std.SetFieldBased(clip2, 0)
clip3 = core.std.SetFieldBased(clip3, 0)
#
Inverse Telecine
Quick inverse telecine filter for converting telecined clips (usually 30 fps interlaced video) back to the original framerate (24 fps progressive).
vivtc
needs to be installed in order for the following snippet to work. You can install it with vsrepo.py install vivtc
.
## Inverse telecine: Fixes telecined video
clip1 = core.vivtc.VFM(clip1, 1)
clip1 = core.vivtc.VDecimate(clip1)
#
Cropping
Crops the source video by n pixels from the selected side. For example, left=20
will remove 20 horizontal pixels starting from the left side. This should be used on sources that use letterboxing or other form of borders.
If you are cropping with odd numbers, you will need to convert your clip to 16-bit depth with 4:4:4 chroma subsampling. (see
## Cropping: Removes letterboxing (black bars) [16-bit required for odd numbers]
clip1 = core.std.Crop(clip1, left=240, right=240, top=0, bottom=0)
clip2 = core.std.Crop(clip2, left=0, right=0, top=276, bottom=276)
clip3 = core.std.Crop(clip3, left=0, right=0, top=21, bottom=21)
Make sure to check for variable aspect ratios throughout the file and only crop the smallest border. We recommend using ShareX for quickly calculating border size.
#
Scaling
Downscales or upscales the video. This should be used to match sources that have differing resolutions.
For upscaling (e.g. 720p -> 1080p), use
EwaLanczos
:## Upscaling: Increases the resolution of clips to match the highest resolution using EwaLanczos (equivalent scaling to mpv's high-quality profile); recommended clip1 = EwaLanczos.scale(clip1, 1920, 1080, sigmoid=False) clip2 = EwaLanczos.scale(clip2, 1920, 1080, sigmoid=False) clip3 = EwaLanczos.scale(clip3, 3840, 2160, sigmoid=False)
For downscaling (e.g. 2160p/4K -> 1080p), use
Hermite
:## Downscaling: Decreases the resolution of clips to match the lowest resolution using Hermite (equivalent scaling to mpv's high-quality profile); not recommended clip1 = Hermite.scale(clip1, 1920, 1080, linear=True) clip2 = Hermite.scale(clip2, 1920, 1080, linear=True) clip3 = Hermite.scale(clip3, 3840, 2160, linear=True)
Downscaling is generally not recommended. We suggest upscaling your sources to match the highest resolution unless you have a specific reason (e.g. comparing how a higher resolution file would look on a lower resolution display).
#
Trimming
Removes the first n frames from the source. For example, [24:]
will skip the first 24 frames and start the source at frame 25. This should be used on sources that are out of sync.
To get the frame difference, find a unique frame (e.g. scene changes) in the correct and incorrect source. Note the frame numbers each one begin at, then set the difference of the two for the incorrect source.
## Trimming: Trim frames to match clips (calculate the frame difference and enter the number here)
clip1 = clip1[0:]
clip2 = clip2[24:]
clip3 = clip3[0:]
For more advanced trimming such as chaining, splicing, and looping, see Vapoursynth's docs.
#
Depth
Converts clips to 16-bit depth with 4:4:4 chroma subsampling. Required for filters such as cropping (with odd numbers) or tonemapping.
## Depth: Convert clips to 16-bit 4:4:4 [required for cropping with odd numbers or tonemapping]
clip1 = core.resize.Lanczos(clip1, format=vs.YUV444P16)
clip2 = core.resize.Lanczos(clip2, format=vs.YUV444P16)
clip3 = core.resize.Lanczos(clip3, format=vs.YUV444P16)
#
Debanding
Sometimes, you might want to compare mpv's real-time debanding. This can be achieved in vs-preview
by matching
mpv's deband settings.
## Convert clips to 32-bit for precision
clip1 = vstools.depth(clip1, 32)
clip2 = vstools.depth(clip2, 32)
clip3 = vstools.depth(clip3, 32)
default_mpv_deband = core.placebo.Deband(clip1, planes=7, iterations=4, threshold=3.44, radius=16.0, grain=0.5)
brazzers_deband = core.placebo.Deband(clip2, planes=7, iterations=4, threshold=5.0, radius=20.0, grain=0.5)
hiroshima_deband = core.placebo.Deband(clip3, planes=7, iterations=4, threshold=7.0, radius=8.0, grain=0.5)
default_mpv_deband = vstools.depth(default_mpv_deband, 8)
brazzers_deband = vstools.depth(brazzers_deband, 8)
hiroshima_deband = vstools.depth(hiroshima_deband, 8)
set_output(default_mpv_deband)
set_output(brazzers_deband)
set_output(hiroshima_deband)
You can find the equivalent mpv profiles here.
#
Tonemapping
Converts the dynamic range of the source (i.e. HDR/DV -> SDR).
- For converting HDR (washed out colors) -> SDR, set
source_colorspace=ColorSpace.HDR10
- For converting DV (green/purple hue) -> SDR, set
source_colorspace=ColorSpace.DOVI
If you want to use tonemapping, you will need to change the color depth to 16-bit (see
## Additional imports [Paste these at the very top of your script]
from awsmfunc.types.placebo import PlaceboColorSpace as ColorSpace
from awsmfunc.types.placebo import PlaceboTonemapFunction as Tonemap
from awsmfunc.types.placebo import PlaceboGamutMapping as Gamut
from awsmfunc.types.placebo import PlaceboTonemapOpts
## Tonemapping: Converts the dynamic range of the source [16-bit required]
## Specify the arguments based on your sources; play with different values when comparing against an SDR source to best match it
clip1args = PlaceboTonemapOpts(source_colorspace=ColorSpace.DOVI, target_colorspace=ColorSpace.SDR, tone_map_function=Tonemap.ST2094_40, gamut_mapping=Gamut.Clip, peak_detect=True, use_dovi=True, contrast_recovery=0.3)
clip2args = PlaceboTonemapOpts(source_colorspace=ColorSpace.HDR10, target_colorspace=ColorSpace.SDR, tone_map_function=Tonemap.ST2094_40, gamut_mapping=Gamut.Clip, peak_detect=True, use_dovi=False, contrast_recovery=0.3)
clip3args = PlaceboTonemapOpts(source_colorspace=ColorSpace.HDR10, target_colorspace=ColorSpace.SDR, tone_map_function=Tonemap.Spline, gamut_mapping=Gamut.Darken, peak_detect=True, use_dovi=False, contrast_recovery=0.3, dst_max=120)
## Apply tonemapping
clip1 = core.placebo.Tonemap(clip1, **clip1args.vsplacebo_dict())
clip2 = core.placebo.Tonemap(clip2, **clip2args.vsplacebo_dict())
clip3 = core.placebo.Tonemap(clip3, **clip3args.vsplacebo_dict())
## Retag video to 709 after tonemapping [required]
clip1 = core.std.SetFrameProps(clip1, _Matrix=vs.MATRIX_BT709, _Transfer=vs.TRANSFER_BT709, _Primaries=vs.PRIMARIES_BT709)
clip2 = core.std.SetFrameProps(clip2, _Matrix=vs.MATRIX_BT709, _Transfer=vs.TRANSFER_BT709, _Primaries=vs.PRIMARIES_BT709)
clip3 = core.std.SetFrameProps(clip3, _Matrix=vs.MATRIX_BT709, _Transfer=vs.TRANSFER_BT709, _Primaries=vs.PRIMARIES_BT709)
Refer to the libplacebo and vs-placebo docs to gain a better understanding of what each parameter does.
#
Range
Sets the color range of the clip as limited (0
) or full (1
). This should be used on sources containing incorrect metadata or after tonemapping DV content (set it to limited).
## Color range: Marks the clip's range as limited (0) or full (1); DV clips will need to be set to limited (0) after tonemapping
clip1 = core.resize.Lanczos(clip1, format=vs.YUV444P16, range=0)
clip2 = core.resize.Lanczos(clip2, format=vs.YUV444P16, range=0)
clip3 = core.resize.Lanczos(clip3, format=vs.YUV444P16, range=1)
#
Gamma
Adjusts the gamma level of the video. This should only be used to fix the QuickTime gamma bug or similar where one source will appear much brighter than the rest.
## Gamma: Fixes gamma bug (i.e. one source is significantly brighter than the others) [32-bit required]
## Convert clips to 32-bit [required for gamma fix]
clip1 = vstools.depth(clip1, 32)
clip2 = vstools.depth(clip2, 32)
clip3 = vstools.depth(clip3, 32)
## Apply fix
clip1 = core.std.Levels(clip1, gamma=0.88, planes=0)
clip2 = core.std.Levels(clip2, gamma=0.88, planes=0)
clip3 = core.std.Levels(clip3, gamma=0.88, planes=0)
#
FrameProps
Set the correct frame properties for your sources. This is most commonly used on sources you're upscaling or 4K SDR content. This should be used on sources with incorrect/missing metadata or colors that are off, particularly reds and greens.
## FrameProps: Repairs sources with incorrect/missing metadata; typically used for 4K SDR and upscaled/downscaled content (colors will be off, particularly reds, greens, and blues)
# SDR: BD/WEB (720p - 4K)
clip1 = core.std.SetFrameProps(clip1, _Matrix=vs.MATRIX_BT709, _Transfer=vs.TRANSFER_BT709, _Primaries=vs.PRIMARIES_BT709)
# SDR: PAL DVD
clip2 = core.std.SetFrameProps(clip2, _Matrix=vs.MATRIX_BT470_BG, _Transfer=vs.TRANSFER_BT470_BG, _Primaries=vs.PRIMARIES_BT470_BG)
# SDR: NTSC DVD
clip3 = core.std.SetFrameProps(clip3, _Matrix=vs.MATRIX_ST170_M, _Transfer=vs.TRANSFER_BT601, _Primaries=vs.PRIMARIES_ST170_M)
# HDR/DV
clip4 = core.std.SetFrameProps(clip4, _Matrix=vs.MATRIX_BT2020_NCL, _Transfer=vs.TRANSFER_BT2020_10, _Primaries=vs.PRIMARIES_BT2020)
#
Double-Range Compression (DRC)
Fixes washed out colors on selected sources.
## Fix DRC: Repairs sources with very washed out colors
clip1 = core.resize.Point(clip1, range_in=0, range=1, dither_type="error_diffusion")
clip1 = core.std.SetFrameProp(clip1, prop="_ColorRange", intval=1)
#
Running
To run your comparison script, launch a terminal window in your working directory and run the following:
vspreview comp.py
Alternatively, you can create a create a comp.bat
file, replacing C:\path\to\comp.py
with the exact file path to your script:
vspreview "C:\path\to\comp.py"
Want to jump straight to making comparisons? See
#
Interface
VSPreview's user-friendly interface allows you to perform many actions while being able to compare sources with ease:
#
Misc
The misc bar contains additional settings for VSPreview.
A simple VSPreview cropping tool. To enable the cropper, set the toggle from OFF to ON.
#
Relative cropping
Relative cropping removes lines of pixels from the side you select. For example, if you set Left to 500
in a 1920x1080
source, VSPreview will remove 500 vertical lines starting from the left-hand side of the video stream, creating a cropped resolution of 1420x1080
.
#
Absolute cropping
Absolute cropping removes lines of pixels starting from the right side (horizontal) or the top/bottom side (vertical). For example, if you set Width to 1420
in a 1920x1080
source, VSPreview will remove 500 vertical lines starting from the right-hand side of the video stream, creating a cropped resolution of 1420x1080
.
Functions for saving frames.
#
File name
By default, VSPreview uses the format {script_name}_{frame}
when saving frames.
We recommend changing the file naming scheme to {frame}_{index}_{Name}
, which is more friendly.
The {Name}
placeholder may include extraneous data in newer versions of VSPreview (e.g. b'sourceName'
instead of sourceName
).
Below is a table of placeholders VSPreview uses:
#
Comp
The comp bar is primarily used for creating
The title of your comparison.
#
Naming scheme
When creating your comparison, we recommend naming it with the show title and sources used. This makes it easier for the user to understand what you are comparing. Some examples are:
- By video source:
The Eminence in Shadow - BD vs. WEB
- By release type:
Watashi no Oshi wa Akuyaku Reijou. - Minis vs. Streams
- By release group:
Miss Kobayashi's Dragon Maid - Okay-Subs vs. Beatrice-Raws
#
Random
The Random parameter sets the number of frames to randomly capture during screenshotting. This is a setting used when creating
For example, a value of 48
means VSPreview will take 48 randomly selected frames from each source when generating the comparison.
Sets the frame type to capture. This is a setting used when creating
Only checked frames are captured. For instance, if I
is unchecked, then VSPreview will only capture P
or B
frames.
The TMDB ID found at TheMovieDB.
- For TV shows, set the box to
TV
- For movies, set the box to
Movie
Tags for Slowpoke Pics collections.
#
Status
The status bar displays several information about the current source:
- 1 - Total number of frames
- The total number of frames in the video stream.
- 2 - Video stream length
- The playback length of the video stream.
- 3 - Video stream resolution
- The content resolution of the video stream.
- 4 - Video format
- The chroma subsampling type and bit depth.
- 5 - Source frame rate
- The frame rate of the video stream, represented by a fraction and approximate decimal.
- 6 - Picture type of current frame
- The picture type of the current frame.
#
Comparing
#
Tips
Label your sources clearly to the user - Try to capture a large variety of scenes (e.g. low/high detail, bright/dark, low/high motion)
- Try to capture frames of the same type
- We recommend taking
P
orB
type frames when possible - This may be harder to accomplish with particular sources, such as streams or WEB-DLs
See how to set a specific frame type
- We recommend taking
#
Basic Keybinds
#
Process
VSPreview offers three methods for creating comparisons:
Automatic comparisons are created completely without any additional user input. VSPreview will automatically select, capture, and upload frames for you. This is the fastest method for creating comparisons.
#
Capturing
In VSPreview, navigate to the bottom bar and toggle the Comp section
Set your parameters. The following parameters should be filled:
- See
Comp for more detail on what each one is used for
- See
Hit the Start Upload button under Comp to begin creating your comparison
Semi-automatic comparisons are created with minor user input. VSPreview will automatically capture and upload frame manually marked by the user. This is the recommended method for creating comparisons.
#
Setup
Locate the frame(s) you want to compare
- By default,
Left arrow
andRight arrow
navigates between frames - See how to
skip frames faster - See
tips on what you should look for
- By default,
Once you find a frame, mark the current frame
- Default keybind:
Ctrl
+Space
- Default keybind:
#
Capturing
In VSPreview, navigate to the bottom bar and toggle the Comp section
Set your parameters. The following parameters should be filled:
- See
Comp for more detail on what each one is used for
- See
Hit the Start Upload button under Comp to begin creating your comparison
Manual comparisons are created completely by the user. VSPreview displays and handles frame capture, while the main actions are performed by the user through the previewer.
#
Capturing
Locate the frame(s) you want to compare
- By default,
Left arrow
andRight arrow
navigates between frames - See how to
skip frames faster - See
tips on what you should look for
- By default,
Once you find a frame, take a screenshot of the current frame
- Default keybind:
Shift
+S
- Default keybind:
If you want to use automatic {frame}_{index}_{Name}
Switch to the other sources and take screenshots of their current frame
- Press the number keys to change sources (e.g.
1
forclip1
,2
forclip2
) - You may need to finely readjust the position using the arrow keys
- Press the number keys to change sources (e.g.
Repeat process for the next frames in your comparison
By default, all frames are stored within your working directory unless manually changed to a different destination.
See
#
QoL Changes
#
VSPreview
You can name your sources in any way you'd like. However, we recommend naming your sources in a way that makes it easy to understand:
How you should name your sources will depend on the content you're comparing. For example, if you are trying to compare HDR and SDR sources, you should include the type in the source name. Generally, the first three will cover most comparisons you make, but you are free to include more as needed.
- In VSPreview, navigate to the bottom bar and toggle the Playback section
- In Playback, set the number of frames to skip (n) when scrubbing by adjusting the first field:
- To skip n frames backward/forward, press
Shift
+Left arrow
/Right arrow
The following guide changes the screenshot key from Shift
+ S
to Enter
:
Launch File Explorer and go to
%localappdata%\Programs\Python\Python312\Lib\site-packages\vspreview\toolbars\misc
In a text editor, open
toolbar.py
Locate the lines below (approximately line 158):
- Use the Find command to locate text (
Ctrl
+F
)
self.main.add_shortcut( QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_S).toCombined(), self.save_frame_as_button.click )
- Use the Find command to locate text (
Replace the lines with the following:
self.main.add_shortcut( (Qt.Key.Key_Return), self.save_frame_as_button.click )
The following guide switches the binds for Left arrow
/Right arrow
and Shift
+ Left arrow
/Shift
+ Right arrow
:
Launch File Explorer and go to
%localappdata%\Programs\Python\Python312\Lib\site-packages\vspreview\toolbars\playback
In a text editor, open
toolbar.py
Locate the lines below (approximately line 180):
- Use the Find command to locate text (
Ctrl
+F
)
self.main.add_shortcut(Qt.Key.Key_Left, self.seek_to_prev_button.click) self.main.add_shortcut(Qt.Key.Key_Right, self.seek_to_next_button.click) self.main.add_shortcut( QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_Left).toCombined(), self.seek_n_frames_b_button.click ) self.main.add_shortcut( QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_Right).toCombined(), self.seek_n_frames_f_button.click )
- Use the Find command to locate text (
Replace the lines with the following:
self.main.add_shortcut( QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_Left), self.seek_to_prev_button.click ) self.main.add_shortcut( QKeyCombination(Qt.Modifier.SHIFT, Qt.Key.Key_Right), self.seek_to_next_button.click ) self.main.add_shortcut(Qt.Key.Key_Left, self.seek_n_frames_b_button.click) self.main.add_shortcut(Qt.Key.Key_Right, self.seek_n_frames_f_button.click)
#
Slowpoke Pics
#
Fetching Account Tokens
If you plan on uploading to Slowpoke Pics (slow.pics) under your account, you will need to provide VSPreview with your account tokens.
- Visit Slowpoke Pics in your browser and log into your account
- Open your browser's Developer Tools. You will need to get two values:
- To get your
browserId
, go to Application -> Storage -> Local Storage ->https://slow.pics
. Copy the key listed there - To get your
sessionId
, go to Network. Refresh the page, then findslow.pics
. In the right-hand section, go to Cookies and copy the Value listed underSLP-SESSION
- To get your
- In VSPreview, go to Settings -> Comp
- Paste the two values in the boxes provided
- Visit Slowpoke Pics in your browser and log into your account
- Open your browser's Developer Tools. You will need to get two values:
- To get your
browserId
, go to Storage -> Local Storage ->https://slow.pics
. Copy the key listed there - To get your
sessionId
, go to Storage -> Cookies ->https://slow.pics
. Copy the key listed underSLP-SESSION
- To get your
- In VSPreview, go to Settings -> Comp
- Paste the two values in the boxes provided
#
Post-processing
The following scripts are best used with
Compresses all .png
image files in the current directory with Oxipng compression (level 1). Runs fast (typically less than a minute to iterate over hundreds of images).
import os
import glob
import subprocess
folder_path = os.getcwd() # Get the current working directory
os.chdir(folder_path) # Change the working directory to the specified folder
image_files = glob.glob("*.png") # Get a list of PNG files in the folder
processes = []
# Divide the image files into chunks of four
image_chunks = [image_files[i:i+4] for i in range(0, len(image_files), 4)]
for images in image_chunks:
command = ["oxipng"] + images + ["-o", "1", "-s", "-a", "-t", "8"]
process = subprocess.Popen(command)
processes.append(process)
# Wait for all processes to finish
for process in processes:
process.wait()
Zero pads frame numbers on images in the current directory and removes extraneous data from file names. This allows for automatic numerical sorting on comp.py
.
import os
def zero_pad_and_clean_file_names():
current_directory = os.getcwd()
for filename in os.listdir(current_directory):
base_name, extension = os.path.splitext(filename)
parts = base_name.split('_')
if len(parts) > 2 and parts[0].isdigit():
parts[0] = parts[0].zfill(5)
parts[2] = parts[2].replace("b'", "").replace("'", "")
new_filename = '_'.join(parts) + extension
os.rename(os.path.join(current_directory, filename), os.path.join(current_directory, new_filename))
# Usage example
zero_pad_and_clean_file_names()
Uploads all .png
image files in the current directory to ptpimg. Requires your ptpimg API key in %USERPROFILE%\.ptpimg.key
.
#!/usr/bin/python
#Windows wildcard support fork - use at your own peril
import sys
import requests
import os
import glob
argc=len(sys.argv)
noconf=0
debug=0
configfile=os.path.join(os.path.expanduser("~"), ".ptpimg.key")
if argc==1:
print("""Usage: ptpimgup.py file1 file2 file3...
Uploads images to ptpimg and spits out http urls of said images
config file %s should contain api_key eg:
01234567-89ab-cdef-0123-456789abcdef
contact oddbondboris with bugs"""%(configfile))
sys.exit()
try:
configfile=os.path.expanduser(configfile)
cfgfile=open(configfile,'r')
apikey=cfgfile.read()[:36]
if len(apikey.split("-")) != 5:
print("bad api key %s, file should only contain the api key"%(apikey))
else:
if debug==1:
print(apikey)
except:
print("broken configi %s"%(configfile))
raise
sys.exit()
finally:
try:
cfgfile.close()
except:
pass
links=[]
if '*' in sys.argv[-1]:
sys.argv[-1:] = glob.glob(sys.argv[-1])
for fname in sys.argv[1:]:
#print fname
try:
curimg=open(os.path.expanduser(fname),'rb')
r=requests.post("https://ptpimg.me/upload.php",files={('file-upload[0]',('lol.png',curimg, 'image/jpg'))},data={'api_key':apikey})
if r.status_code==200:
print("https://ptpimg.me/%s.%s"%(r.json()[0]['code'],r.json()[0]['ext']))
links.append(("https://ptpimg.me/%s.%s"%(r.json()[0]['code'],r.json()[0]['ext']),fname))
else:
print("error uploading file %s http %s"%(fname,r.status_code))
except IOError as e:
print("error on file %s : %s"%(fname,e.strerror))
finally:
try:
curimg.close()
except:
pass
for link in links:
print("[img]%s[/img]"%(link[0]))
for link in links:
print("%s %s"%(link))
#
Additional Scripts
#
Automation
If VSPreview is too complicated to setup, you can use McBaws' script to automatically generate the comparisons for you. Do note, this is far less powerful than just using VSPreview.