View Full Version : ImageMagick writer/reader
Myrsloik
4th August 2014, 22:07
I made a simple image reader and writer since people don't have much luck with the existing ones.
Usage examples:
core.imwri.Read('E:/testdir/testimg000001.png', alpha=False)
core.imwri.Write(main, 'PNG32', 'E:/testdir/testimg%06d.png')
Documentation (https://raw.githubusercontent.com/vapoursynth/vapoursynth/master/doc/plugins/imwri.rst)
imwri test9 32bit (https://www.dropbox.com/s/viie4ztrn45dbqy/imwri-r41-win32.7z?dl=1)
imwri test9 64bit (https://www.dropbox.com/s/wti4n0y4wvwibal/imwri-r41-win64.7z?dl=1)
sneaker_ger
4th August 2014, 23:35
How is the dllpath thing supposed to work after the plugin should've already been loaded?
Myrsloik
5th August 2014, 00:17
How is the dllpath thing supposed to work after the plugin should've already been loaded?
That's a very good question. Basically ImageMagick decided that normal library ideas were too mundane.
So you not ONLY need to link against imagemagick using your standard .lib files in windows. The linking gives you access to a function in imagemagick so you can tell imagemagick where to find all its other dlls after the main dll has been loaded. It's dll hell illustrated.
A normal library (which this is most certainly not) simply would've loaded all its parts at once.
sneaker_ger
5th August 2014, 09:30
Well, I can't even get past LoadPlugin because of missing dlls even when they are in the same directory as imwri.dll.
Myrsloik
5th August 2014, 10:34
I'll look at it a bit more later but this is how I tested it:
I only used vspipe, I made sure both the script and all the plugin files are in the same directory AND that the working directory is the script directory.
I'll see if I can modify the source a bit and use mingw instead for the test versions as well...
sneaker_ger
5th August 2014, 13:11
Running the script from the same folder as the dlls yields success. I had only tried running vspipe from the dll folder prior to this.
Mystery Keeper
5th August 2014, 14:17
The most simple solution is to add dlls folder to PATH environment variable.
Myrsloik
6th August 2014, 23:41
I've added a second test version that's compiled for 64 bits (link in the first post). Nodame worked long and hard and managed to make it a single dll so the dllpath argument isn't needed anymore.
Report on your success/failures with unicode filenames.
This plugin will be added to the main source tree once it's working well enough.
LoRd_MuldeR
7th August 2014, 01:28
Well, I can't even get past LoadPlugin because of missing dlls even when they are in the same directory as imwri.dll.Running the script from the same folder as the dlls yields success. I had only tried running vspipe from the dll folder prior to this.
Keep in mind that Windows only looks for DLL's in the same folder where the main EXE file is located. But if some DLL depends on additional DLL's, it will not necessarily look in the folder where the DLL is located.
For example, if some EXE file explicitly loads a plug-in DLL from a certain "plug-ins" directory that differs from the directory where the EXE file itself is located and if that plug-in DLL depends on yet another DLL, then Windows will not look in the "plug-ins" directory for that other DLL (as one might expect) - it still only looks in the folder where the main EXE resides!
If the required DLL could not be found in the directory where the EXE file is located, Windows falls back to certain system directories (C:\Windows\System32, C:\Windows, etc). Then to the directories contained in the PATH environment variable. And finally it falls back to the "current" directory. So that's probably why "running the script from the same folder as the dlls" worked, because that happened to be your "current" directory then.
Myrsloik
7th August 2014, 11:41
First post once again updated with an improved version. Nodame managed to add in support for even more formats in the static builds and now both versions are a single simple dll.
The dllpath argument is dead!
So start testing. This should work and only be a minimal hassle to use now.
alexxdls
12th August 2014, 07:01
Can this plugin read image sequence? I've tried ext = '.png'
dir = r"F:\TEMP\50-SHADES_TRL-A_RU-XX_RU_51_1080P_UP_20140725_MPS_IOP_OV\REEL1/"
srcs = [dir + src for src in os.listdir(dir) if src.endswith(ext)]
v1 = core.imwri.Read(srcs)like with previoous ImageReader, but it now outputs only the first image and all frames are equal. Checking the script givesScript was successfully evaluated. Output video info:
Frames: 341 | Time: 0:00:14.208 | Size: 1920x1080 | FPS: 24/1 = 24 | Format: YUV444P10
Myrsloik
12th August 2014, 07:52
Can this plugin read image sequence? I've tried ext = '.png'
dir = r"F:\TEMP\50-SHADES_TRL-A_RU-XX_RU_51_1080P_UP_20140725_MPS_IOP_OV\REEL1/"
srcs = [dir + src for src in os.listdir(dir) if src.endswith(ext)]
v1 = core.imwri.Read(srcs)like with previoous ImageReader, but it now outputs only the first image and all frames are equal. Checking the script givesScript was successfully evaluated. Output video info:
Frames: 341 | Time: 0:00:14.208 | Size: 1920x1080 | FPS: 24/1 = 24 | Format: YUV444P10
Found the typo in the code. Will post a fixed version in a bit.
kolak
12th August 2014, 21:25
Does it read fps from DPX header?
Does read support same % mode as write, eg.
test_%03d.tiff for test_001, test_002, test_003,..... image sequence?
Myrsloik
12th August 2014, 21:26
Does it read fps from DPX header?
No, not yet at least.
kolak
12th August 2014, 21:30
What format are files decoded to, x bit RGB?
Myrsloik
12th August 2014, 21:36
IMPORTANT ANNOUNCEMENT
The test2 archive has been updated. It now handles reading lists of files properly. Before it would simply return the first image over and over again due to a typo. Get it from the first post.
What format are files decoded to, x bit RGB?
Only 8-16 bit rgb for now. Going to try to add proper grayscale and yuv in a bit. Returning original subsampled data (such as 420 jpeg) is probably impossible with imagemagick.
kolak
12th August 2014, 21:50
RGB is good in this case, I assume.
Wilbert
12th August 2014, 21:55
Returning original subsampled data (such as 420 jpeg) is probably impossible with imagemagick.
I never implemented this in Immaavs, but i always thought that this would be possible. Please let us know if that's not the case.
Myrsloik
13th August 2014, 00:08
Now I've encountered another problem. I have no test images that are identified as being in a yuv-ish colorspace so I can't add support for reading them. Apparently jpeg images aren't considered yuv.
My own web hunt for this kind of image failed so sample images are requested.
foxyshadis
13th August 2014, 00:41
I never implemented this in Immaavs, but i always thought that this would be possible. Please let us know if that's not the case.
I did see that thread you made (http://www.imagemagick.org/discourse-server/viewtopic.php?f=2&t=14645), but I see your last question was never answered. You'd have to mod coders/jpeg.c to change:
i=(ssize_t) jpeg_read_header(&jpeg_info,TRUE);
if ((image_info->colorspace == YCbCrColorspace) ||
(image_info->colorspace == Rec601YCbCrColorspace) ||
(image_info->colorspace == Rec709YCbCrColorspace))
jpeg_info.out_color_space=JCS_YCbCr;
to:
i=(ssize_t) jpeg_read_header(&jpeg_info,TRUE);
if (image_info->colorspace == UndefinedColorspace)
jpeg_info.out_color_space=jpeg_info.jpeg_color_space;
else if ((image_info->colorspace == YCbCrColorspace) ||
(image_info->colorspace == Rec601YCbCrColorspace) ||
(image_info->colorspace == Rec709YCbCrColorspace))
jpeg_info.out_color_space=JCS_YCbCr;
and then rebuild. Or just use your own code to detect it ahead of time.
There is a flag that IM doesn't use, jpeg_info.raw_data_out, that will give you non-upsampled pixels. Without it they're always upsampled with a bilinear filter. You'd have to write a bit of code to trick IM into working, since its routines won't work; you have to use jpeg_read_raw_data() instead of jpeg_read_scanlines() and fill the RGB buffers as you wish.
(I forgot how much of a migraine reading IM's source gives me.)
foxyshadis
13th August 2014, 00:42
Now I've encountered another problem. I have no test images that are identified as being in a yuv-ish colorspace so I can't add support for reading them. Apparently jpeg images aren't considered yuv.
My own web hunt for this kind of image failed so sample images are requested.
Practically all JPEG images are YCbCr. (Rec.601 fullscale, to be exact.) IM just doesn't report them as such, since it converts them to RGB normally, though it also supports CMYK and Lab.
alexxdls
13th August 2014, 03:19
IMPORTANT ANNOUNCEMENT
The test2 archive has been updated. It now handles reading lists of files properly. Before it would simply return the first image over and over again due to a typo. Get it from the first post..Thanks. It works fine now. But could you give a look on my report about VapourSynth here https://www.doom9.org/showpost.php?p=1689749&postcount=1339 and here https://www.doom9.org/showpost.php?p=1689811&postcount=1341
Please
And just one note moreimport vapoursynth as vs
core = vs.get_core()
import os
core.std.LoadPlugin(path=r"d:\TOOLS\MyDCPConverter\Tools\imwri-64.dll")
core.std.LoadPlugin(path=r"d:\TOOLS\MyDCPConverter\Tools\fmtconv.dll")
vl = core.imwri.Read(r"F:\TEMP\TRAIN-DRAGON-2_TLR-G-3D_RU-XX_RU-00_51_2K_TCF_20140417_DWA_IOP-3D\REEL2\000034L.png")
vr = core.imwri.Read(r"F:\TEMP\TRAIN-DRAGON-2_TLR-G-3D_RU-XX_RU-00_51_2K_TCF_20140417_DWA_IOP-3D\REEL2\000034R.png")
v = core.std.StackHorizontal([vl,vr])
v.set_output()
Withvr = vlthe script goes well, but withvr = core.imwri.Read(r"F:\TEMP\TRAIN-DRAGON-2_TLR-G-3D_RU-XX_RU-00_51_2K_TCF_20140417_DWA_IOP-3D\REEL2\000034L.png")doesn't, again. But now vr equals vl. What is the difference?
It seems like I can't output video with two different imwri.Read's, doesn't it?
Myrsloik
13th August 2014, 13:32
It actually appears to be because of how imagemagick was compiled when creating a single file plugin. The error message actually comes from pthreads. I'm trying to think of how to fix it.
Anyway, next update will have grayscale support.
kolak
17th August 2014, 18:58
How do I load image sequence?
I've tried test_%03d.tif, but it did not work.
Loading single files was fine.
Myrsloik
17th August 2014, 19:00
How do I load image sequence?
I've tried test_%03d.tif, but it did not work.
Loading single files was fine.
That's how you do it. Are the files named test_000.tif, test_001.tif...?
kolak
17th August 2014, 19:12
Yes. It says that files can't be found. Does it have to start with 0?
Myrsloik
17th August 2014, 19:13
Yes. It says that files can't be found.
Try using the full path. And yes, it has to start at 0 at the moment.
kolak
17th August 2014, 19:24
This is probably the reason. Mine starts from 1. Can we have start number as a variable?
Myrsloik
17th August 2014, 19:30
This is probably the reason. Mine starts from 1. Can we have start number as a variable?
Yes, I'll add it for the next test version.
kolak
17th August 2014, 19:37
How does the writer work.
I tried
s=source...
core.imwri.Write(s, 'DPX', 'D:\test_%03d.dpx')
And put script through vspipe.
Nothing written to the disk. Script itself givses correct output.
jackoneill
18th August 2014, 00:51
How does the writer work.
I tried
s=source...
core.imwri.Write(s, 'DPX', 'D:\test_%03d.dpx')
And put script through vspipe.
Nothing written to the disk. Script itself givses correct output.
s = source
s = core.imwri.Write(s, ...)
s.set_output()
Frames that aren't requested from imwri.Write() aren't written.
kolak
18th August 2014, 08:15
Thank you.
I figured it out.
alexxdls
18th August 2014, 14:30
How do I load image sequence?
I've tried test_%03d.tif, but it did not work.
Loading single files was fine.dir = r"dir\path/"
srcs = [dir + src for src in os.listdir(dir)]
v = core.imwri.Read(srcs)works fine for loading images from directory
kolak
18th August 2014, 14:44
%xd also works, but only when your first image has number 0.
When I tried your method I had error saying:
"Don't know what os means".
sneaker_ger
18th August 2014, 19:54
You need "import os" at the top of your script.
kolak
21st August 2014, 13:10
Thx.
Will try.
alexxdls
23rd August 2014, 04:00
Any update in near future?
Myrsloik
24th August 2014, 01:16
Any update in near future?
Maybe in a day or two when I finish all the big changes. I decided to go back and redo a fairly big amount of code because the C++ api is useless.
alexxdls
24th August 2014, 05:51
Maybe in a day or two when I finish all the big changes. I decided to go back and redo a fairly big amount of code because the C++ api is useless.Thanks. I hope you will be able to solve an issue with stacking two different image seqeunces.
Myrsloik
24th August 2014, 18:11
Third test and a small list of notable changes in the first post. The dllpath argument is back and so is the dll mess. I'll probably get around to making a single file dll compile some day with mingw. But that's complicated.
This should more or less be the final version. ImageMagick as a library is simply too abstracted/awkward/horrible to use to return native colorspaces. On the positive side I think it can do most important things, read and write a big pile of formats as image sequences. If I ever locate a better library to use maybe I'll have another go. And remember that ffms2 also works for image reading if you want to try something else.
alexxdls
25th August 2014, 03:08
And remember that ffms2 also works for image reading if you want to try something else.I dubt it supports high bit depth images...
kolak
25th August 2014, 12:35
It does, as it's based on ffmpeg.
vcmohan
27th October 2014, 12:29
! am confused. I tried to load the imwri.dll from test3.
It gave a message cannot load plugin
Should I use test 2 plugin? I am using 32 bit only.
Reel.Deel
6th November 2014, 03:06
@Myrsloik
Any possibility of a single plugin for r25?
Myrsloik
6th November 2014, 10:34
@Myrsloik
Any possibility of a single plugin for r25?
I at least have one workaround in mind so dllpath won't be needed anymore now that plugins can get their own path in r25. No idea if my mingw skills will be enough to slap it into single file submission though. But I'll try. Higher on the list is alpha support in FFMS2 though. Poor linux users can have no alpha...
Myrsloik
25th November 2014, 16:54
Posted test4 in both 32 and 64 bit versions. This one removes dllpath and needs vs R25. In combination with vs R25 it can easily be loaded with loadplugin or autoloaded (if you dump that huge lump of files into the autoload directory, not recommended but it should work).
It also has a slightly newer imagemagick but with ffmpeg.exe removed (don't try to read mpeg files it). Try it and see what happens. Apart from being usable there are no other improvements since I don't feel like making my own imagemagick distribution.
MonoS
21st December 2014, 00:16
I get this error using VapourSynth Editor
vapoursynth.Error: Read: Failed to read image properties: vsedit-32bit.exe: RegistryKeyLookupFailed `CoderModulesPath' @ error/module.c/GetMagickModulePath/662
The script is this one
import vapoursynth as vs
core = vs.get_core()
core.std.LoadPlugin("C:/Program Files (x86)/VapourSynth/plugins32/imwri/imwri.dll")
src = core.imwri.Read('C:/Users/MonoS/Desktop/Personale/B2wAZhvIgAEraOP.png')
src.set_output()
Myrsloik
21st December 2014, 00:22
I get this error using VapourSynth Editor
...
Does that happen with all image files or just that one? Does it work outside the editor?
MonoS
21st December 2014, 17:12
Nothing, tried using vspipe and changing file, but nothing, still the same error
18fps
23rd December 2014, 15:05
I dubt it supports high bit depth images...
What it does not supports is image sequences, only single images.
kolak
27th December 2014, 15:35
It does support sequences also, just use ffmpeg naming convention for image sequences.
Myrsloik
7th January 2015, 21:06
Nothing, tried using vspipe and changing file, but nothing, still the same error
Confirmed. Apparently it still looks for the already installed imagemagick binaries for some reason.
Myrsloik
14th January 2015, 00:18
After an evening of debugging I can proudly report that ImageMagick has some of the worst code I've looked at in a while. Including my own ancient YATTA code.
It automatically initializes itself when its dlls are loaded and it misuses its own api to set the path to use so it can never work. I suggest you send hate letters to the ImageMagick developers so they stop writing code. The world will be better off that way.
Reel.Deel
14th January 2015, 02:32
That's a pity to hear that. If I'm understanding correctly this is the end of imwri? Are there better alternatives? Could ffmpeg be used to write images (similar to ffms2 but for exporting)?
Myrsloik
14th January 2015, 02:37
That's a pity to hear that. If I'm understanding correctly this is the end of imwri? Are there better alternatives? Could ffmpeg be used to write images (similar to ffms2 but for exporting)?
It's only a maybe end. If they apply the changes in my bug report it can still be made to work. Have to wait and see. I could also compile my own fixed binaries but that's extremely annoying and the build system on windows is a joke.
Myrsloik
14th January 2015, 14:55
A small update. My fix has been accepted and the next ImageMagick release will have it. Expect a new and finally properly self contained release when version 6.9.0-4 is out.
MonoS
19th January 2015, 01:38
The impossible is happened
Thank you
Myrsloik
28th January 2015, 23:45
HAHAHA! YOU THOUGHT THE STORY WOULD END HERE? FOOLS!
The ImageMagick developers decided to simply release the broken 6.9.0-3 binaries as 6.9.0-4. Because why not? They've now wasted yet another evening for me. Maybe one day they'll get around to release updated binaries...
MonoS
29th January 2015, 12:47
WTF, wonderful!
I saw some 7.0 binaries in some repo, maybe they are preparing your commit for the next release??
Myrsloik
12th February 2015, 00:36
Here's test6 (https://www.dropbox.com/s/no628ujeuhd1gfo/imwri_test6.7z?dl=1). Tell me if it works. Only briefly tested.
Had to compile my own imagemagick binaries because that's how shit the official ones are. At least it appears to work.
MonoS
12th February 2015, 14:35
I'm trying it right now with the exr from BBB.
It seems to work really well, if i have some spare cpu in the next years maybe there will be a 16bit h265 lossless version of BBB thanks to vapoursynth :D
Myrsloik
12th February 2015, 14:44
If this version is confirmed to mostly work I'll probably go on and add float output support as well since it's a very small modification to do.
...some day.
MonoS
12th February 2015, 15:33
Maybe something don't work quite well, but i don't know.
Importing the exr from BBB [16bit float] the format is specified as RGB48 and not RGBS.
Is this expected??
Myrsloik
12th February 2015, 15:35
Maybe something don't work quite well, but i don't know.
Importing the exr from BBB [16bit float] the format is specified as RGB48 and not RGBS.
Is this expected??
Yes. Imagemagick is retarded so at compile time you have to specify the image format. For all images opened... Ever. This is why I may add float support later.
MonoS
12th February 2015, 15:43
I bet they won the Ig Nobel for programing at some point :D
Kupildivan
20th February 2015, 06:52
I've done this script:
import vapoursynth as vs
core = vs.get_core()
v = core.ffms2.Source ('HOB2.mkv')
v = core.std.Trim (v, 1600, 1701)
v = core.fmtc.matrix (v, mat="709", col_fam=vs.RGB, bits=16)
v = core.imwri.Write (v, 'PNG48', 'IMG\%05d.png')
v.set_output()
and the .bat file for it:
"C:\Program Files (x86)\VapourSynth\core64\vspipe.exe" VS.vpy -
that writes on disk only 7 first images and cmd hangs.
How to write all of these 101 images proprerly?
Myrsloik
20th February 2015, 12:54
I've done this script:
import vapoursynth as vs
core = vs.get_core()
v = core.ffms2.Source ('HOB2.mkv')
v = core.std.Trim (v, 1600, 1701)
v = core.fmtc.matrix (v, mat="709", col_fam=vs.RGB, bits=16)
v = core.imwri.Write (v, 'PNG48', 'IMG\%05d.png')
v.set_output()
and the .bat file for it:
"C:\Program Files (x86)\VapourSynth\core64\vspipe.exe" VS.vpy -
that writes on disk only 7 first images and cmd hangs.
How to write all of these 101 images proprerly?
I'll have to test it myself and see. I mostly tested reading images acutally...
sneaker_ger
20th February 2015, 20:54
Try piping to NUL:
"C:\Program Files (x86)\VapourSynth\core64\vspipe.exe" VS.vpy NUL
Kupildivan
21st February 2015, 04:39
Try piping to NUL:
"C:\Program Files (x86)\VapourSynth\core64\vspipe.exe" VS.vpy NUL
It's worked for me - "Output 102 frames in 217.67 seconds (0.47 fps)".
As for real writing I forgot to mention when I click on that .bat file cmd window begins to draw very long sequence of symbols for a while and then it hangs without suggesting to close it until I click on it.
I suppose I have done a mistake somewhere in the script or bat.
jackoneill
21st February 2015, 08:59
It's worked for me - "Output 102 frames in 217.67 seconds (0.47 fps)".
As for real writing I forgot to mention when I click on that .bat file cmd window begins to draw very long sequence of symbols for a while and then it hangs without suggesting to close it until I click on it.
I suppose I have done a mistake somewhere in the script or bat.
Yes. The hyphen (which you replaced with "NUL") tells vspipe to write the output to stdout, i.e. dump it all in the cmd window.
Kupildivan
22nd February 2015, 12:01
I knew it. Anyway it doesn't matter, for I found another way to convert 10-bit mkv to png in the neighbour thread:
%ffmpeg% -i "Хоббит. Битва пяти воинств - Трейлер №2 в 3D [DCPrip 2K Hi444PP Hi10P OU].mkv" IMG\%%04d.png
Even without forcing 16-bits to output it creates correct sequence of PNG48 by default for such video.
sneaker_ger
23rd July 2015, 12:51
Can someone with a clean R27 Windows install check whether or not he has the ImageMagick plugin? I thought it's supposed to come with the VapourSynth package nowadays but it seems to be missing here. Or at least it does not load here (Win 7 x64, no AVX CPU)
ret = core.imwri.Read('graded_edit_%05d.tiff')
"Python exception: No attribute with the name imwri exists"
Myrsloik
23rd July 2015, 12:59
It's not included and never will be due to its insane size.
sneaker_ger
23rd July 2015, 12:59
It's listed as included in the docs:
http://www.vapoursynth.com/doc/includedplugins.html
Myrsloik
23rd July 2015, 13:01
That should be read as "included in the source tree"
dipje
30th July 2015, 15:14
I'm able to write EXR images no problem, but they get saved as (if I see it correctly) full 32-bit floating-point uncompressed files. Or at least 16-bit FP uncompressed.. ie huge :).
The ImageMagick build seems to have support for other compression types (For example 'piz') since it's listed in the output that convert.exe and mogrify.exe give.
So is it possible to add a parameter to specify compression type (also handy for things like TIFF and such), or at least change the default for EXR somehow?
I'm also willing to mock around and try to change + compile it for my own, but you said you used a custom-built ImageMagick for all this. Is that located somewhere so it's easier for me to recompile imwri.dll against your ImageMagick build?
Myrsloik
30th July 2015, 15:55
I'm able to write EXR images no problem, but they get saved as (if I see it correctly) full 32-bit floating-point uncompressed files. Or at least 16-bit FP uncompressed.. ie huge :).
The ImageMagick build seems to have support for other compression types (For example 'piz') since it's listed in the output that convert.exe and mogrify.exe give.
So is it possible to add a parameter to specify compression type (also handy for things like TIFF and such), or at least change the default for EXR somehow?
I'm also willing to mock around and try to change + compile it for my own, but you said you used a custom-built ImageMagick for all this. Is that located somewhere so it's easier for me to recompile imwri.dll against your ImageMagick build?
You can use the official sdk stuff I think. Just grab the actual dlls from my version. I think that should work.
I'll add an argument for compression type and that stuff some day. Actually I completely forgot about it since I mostly tested with png.
dipje
3rd August 2015, 16:25
Had a bit of a fight to understand how the ImageMagick build-thingy works. Actually reading the manual helped :S, so I got _something_ build for MSVC 2010 with a slightly more recent ImageMagick built than what you used.
Then, as you said, used it just to compile my imwri.dll and just replaced that in my Vapoursynth folder, so using your DLLs. Stuff works.
Had to fight a bit to get imwri.cpp compiling under MSVC 2010, since you seem to be using some c++11 stuff. After it compiled and worked, added a simple 'compresstype' optional string parameter, then used an ugly 'if else if else'-block to match the strings to image.compressType() calls, and tadaaah. Seems to be working. Full-hd EXR files go from 16mb to +/- 6mb with Piz compression enabled while still being lossless and some sort of deep color. Finally a nice way to go in-and-out of After Effects / Vapoursynth :).
kaefert
4th August 2015, 22:27
how can the imwri plugin be compiled on linux? I've followed the guide here: http://www.vapoursynth.com/doc/installation.html#linux-and-os-x-installation-instructions but this did not compile the imwri plugin, only a few others.
@dipje what manual do you mean? is there some manual for compiling imwri somewhere?
UPDATE: Okey. So far thats what I managed to do:
cd ~/src/vapoursynth/src/filters/imwri
g++ -std=c++0x -I/usr/include/ImageMagick/ -I/home/kaefert/src/vapoursynth/include/ imwri.cpp
which still gives quite a few errors:
imwri.cpp: In function ‘const VSFrameRef* writeGetFrame(int, int, void**, void**, VSFrameContext*, VSCore*, const VSAPI*)’:
imwri.cpp:169:19: error: ‘class Magick::Image’ has no member named ‘quantizeDitherMethod’
image.quantizeDitherMethod(Magick::FloydSteinbergDitherMethod);
^
imwri.cpp:169:40: error: ‘FloydSteinbergDitherMethod’ is not a member of ‘Magick’
image.quantizeDitherMethod(Magick::FloydSteinbergDitherMethod);
^
imwri.cpp:169:40: note: suggested alternative:
In file included from /usr/include/ImageMagick/magick/deprecate.h:34:0,
from /usr/include/ImageMagick/magick/MagickCore.h:85,
from /usr/include/ImageMagick/Magick++/Include.h:43,
from /usr/include/ImageMagick/Magick++.h:9,
from imwri.cpp:27:
/usr/include/ImageMagick/magick/quantize.h:32:3: note: ‘FloydSteinbergDitherMethod’
FloydSteinbergDitherMethod
^
imwri.cpp:173:23: error: ‘class Magick::Image’ has no member named ‘alphaChannel’
image.alphaChannel(Magick::ActivateAlphaChannel);
^
imwri.cpp:173:36: error: ‘ActivateAlphaChannel’ is not a member of ‘Magick’
image.alphaChannel(Magick::ActivateAlphaChannel);
^
imwri.cpp:173:36: note: suggested alternative:
In file included from /usr/include/ImageMagick/magick/draw.h:26:0,
from /usr/include/ImageMagick/magick/annotate.h:25,
from /usr/include/ImageMagick/magick/MagickCore.h:66,
from /usr/include/ImageMagick/Magick++/Include.h:43,
from /usr/include/ImageMagick/Magick++.h:9,
from imwri.cpp:27:
/usr/include/ImageMagick/magick/image.h:33:3: note: ‘ActivateAlphaChannel’
ActivateAlphaChannel,
^
imwri.cpp: In function ‘void readCreate(const VSMap*, VSMap*, void*, VSCore*, const VSAPI*)’:
imwri.cpp:572:58: warning: narrowing conversion of ‘d.std::unique_ptr<_Tp, _Dp>::operator-><ReadData, std::default_delete<ReadData> >()->ReadData::filenames.std::vector<_Tp, _Alloc>::size<std::basic_string<char>, std::allocator<std::basic_string<char> > >()’ from ‘std::vector<std::basic_string<char> >::size_type {aka long unsigned int}’ to ‘int’ inside { } [-Wnarrowing]
d->vi[0] = { nullptr, 30, 1, 0, 0, d->filenames.size(), 0 };
update2: okey, so I guess maybe the imagemagick version included in my distribution is too old (8:6.7.7.10-6ubuntu3 --> 6.7.7.10)
I'm gonna try and update
jackoneill
5th August 2015, 07:26
how can the imwri plugin be compiled on linux? I've followed the guide here: http://www.vapoursynth.com/doc/installation.html#linux-and-os-x-installation-instructions but this did not compile the imwri plugin, only a few others.
You need to pass '--enable-imwri' to configure. It's right there in the output of 'configure --help'.
kaefert
5th August 2015, 10:21
thanks jackoneill! That worked!
now I only need to find out how to overlay my clip loaded with the imwri filter from png files over another clip.
http://www.vapoursynth.com/doc/avisynthcomp.html says I need to use std.Lut2 or std.Expr.
From reading http://www.vapoursynth.com/doc/plugins/imwri.html I guess I need to get the alpha channel as a seperate clip and somehow use this to tell std.Lut2 or std.Expr which parts of the png are transparent
UPDATE: okey, so I've found that I can get the images + their alpha channel in 2 seperate clips like this:
[bb,ba] = core.imwri.Read(filename="LOG00103.01/LOG00103.01.%06d.png", firstnum=0, alpha=True)
now all I need is some way to overlay every frame from bb according to the alpha info from the according frame in ba over the frames of some 3rd clip which contains my video
dipje
5th August 2015, 11:07
@kaefert I was talking about the ImageMagick manual, had nothing to do (yet) with imwri
kaefert
5th August 2015, 11:42
@kaefert I was talking about the ImageMagick manual, had nothing to do (yet) with imwri
okey, no problem. jackoneill told me the solution, so that problem is solved. Now I only need to learn how to use std.Expr and or std.Lut2 to overlay a transparent png clip over a video. I've done something similar before - dissolving two clips - if I can't find out how to do it with Expr or Lut2, maybe I'll try to adapt that code to my current needs:
def dissolve(clip1, clip2):
fade_frames = [clip1[0:clip1.num_frames-dissolveCount]]
for i in range(dissolveCount):
frame1 = clip1[clip1.num_frames - dissolveCount + i]
frame2 = clip2[i]
fade_frames.append(core.std.Merge(clipa=frame1, clipb=frame2, weight=i/(dissolveCount-1)))
fade_frames.append(clip2[dissolveCount:clip2.num_frames])
return core.std.Splice(clips=fade_frames)
splinter98
5th August 2015, 12:44
now all I need is some way to overlay every frame from bb according to the alpha info from the according frame in ba over the frames of some 3rd clip which contains my video
You need to addborders to your alpha clip so it matches the resolution of the clip you're overlaying onto, then use MaskedMerge to overlay them.
I have the following function which I use:
def Overlay(clipa, clipb, x=0,y=0, alpha=None):
core = vs.get_core()
if alpha is None:
#Create Blank Alpha Mask
alpha = core.std.BlankClip(clipb, color=[0xFF,0xFF,0xFF])
if clipb.format.id != clipa.format.id:
#Change clip b to same image type as clip a
clipb = core.resize.Bicubic(clipb, format=clipa.format.id)
if alpha.format.id != clipa.format.id:
#Change alpha to clip a format
alpha = core.resize.Bicubic(alpha, format=clipa.format.id)
#Calculate padding sizes
l, r = x, (clipa.width - clipb.width - x)
t, b = y, (clipa.height - clipb.height - y)
#Add padding
mask = core.std.AddBorders(alpha,l,r,t,b)
layer = core.std.AddBorders(clipb,l,r,t,b)
#return padded clips
return core.std.MaskedMerge(clipa, layer, mask, first_plane=True)
clip = overlay(clip, bb, x=20, y 30, ba)
kaefert
5th August 2015, 12:58
wow! thanks splinter98! however, in the return statement of your function you use a variable called "output" that is not defined anywhere
UPDATE: okey, found quite quickly that "output" was supposed to be "clipa"
update2: this question is not really to much related to this thread, but here it is anyway:
Is there a way to get seekable output from vapoursynth?
I currently preview my output using
vspipe playground.vpy --y4m - | mpv -
but mpv will tell me "Can't seek in this file." (of course, since its playing std input)
I found here:
https://wiki.archlinux.org/index.php/Mpv#Vapoursynth
that mpv can be compiled with VapourSynth support using the --enable-vapoursynth flag
I've installed the mpv release from this repository:
https://launchpad.net/~djcj/+archive/ubuntu/vapoursynth
So my mpv should have this flag set. Can this be used to simply play a vpy script instead of using one as a filter (as described on the archlinux wiki)?
mpv playground.vpy gives me Failed to recognize file format.
using
mpv --vf=vapoursynth=playground.vpy someunusedfile.avi
I can also get a preview of my script's output, but mpv will crash when I try to seek the output
UPDATE3: I've found vsedit - it can preview and select specific frames, but it lacks the feature to simply play the script, you can only go one from back or forward using arrows, or 10 frames back or forward using pageup & pagedown - or select a frame on the timeline or enter its number in a box. but not playing and if you "fake-play" by holding down an arrow key but that will continue playing for me after releasing the arrow key because it stacks "give me the next frame" messages instead of listening to keydown and keyup or something like that.
splinter98
5th August 2015, 14:13
wow! thanks splinter98! however, in the return statement of your function you use a variable called "output" that is not defined anywhere
UPDATE: okey, found quite quickly that "output" was supposed to be "clipa"
Ah yes you're correct, I simplified my code as I have it broken up into three separate functions (which allows me to prepare a whole set clips to overlay and then to the final merge with a single function call), so output is just a rename fail. I will update the code for anyone else who uses the code.
splinter98
5th August 2015, 23:33
I assume we should use mask instead of alpha here.
Yes! I really should test my code before publishing.
kaefert
6th August 2015, 09:32
hey there! I've added some functionality to splinter98's function (allow x & y values that move part of the overlay out of the base clip) and thought I'd share it, maybe its useful for other people too:
def Overlay(clipa, clipb, x=0,y=0, alpha=None):
if alpha is None:
#Create Blank Alpha Mask
alpha = core.std.BlankClip(clipb, color=[0xFF,0xFF,0xFF])
if clipb.format.id != clipa.format.id:
#Change clip b to same image type as clip a
clipb = core.resize.Bicubic(clipb, format=clipa.format.id)
if alpha.format.id != clipa.format.id:
#Change alpha to clip a format
alpha = core.resize.Bicubic(alpha, format=clipa.format.id)
#Calculate padding sizes
l, r = x, (clipa.width - clipb.width - x)
t, b = y, (clipa.height - clipb.height - y)
#split into crop and padding values
cl, pl = min(l,0)*-1, max(l,0)
cr, pr = min(r,0)*-1, max(r,0)
ct, pt = min(t,0)*-1, max(t,0)
cb, pb = min(b,0)*-1, max(b,0)
#crop and padding
alpha = core.std.CropRel(alpha,cl,cr,ct,cb)
clipb = core.std.CropRel(clipb,cl,cr,ct,cb)
mask = core.std.AddBorders(alpha,pl,pr,pt,pb)
layer = core.std.AddBorders(clipb,pl,pr,pt,pb)
#return padded clips
#print(clipa, layer, mask)
return core.std.MaskedMerge(clipa, layer, mask, first_plane=True)
Myrsloik
30th January 2016, 03:15
Test7 released. All output will be float. I think.
jackoneill did the compiling so now it's a much smaller set of files. Report your findings.
dipje
31st January 2016, 00:17
So, imwri can now be compiled against a Q32 or a Q16 ImageMagick, and it becomes 'imwrif' or 'imwri' namespace depending on which library it is compiled again?
Or it supports both Q16 and Q32 at the same time and you need to use the appropriate namespace?
If the first case is true, what version is included in test7? The files are way different than previous ImageMagick builds. Is that a new 'condensed all in one' ImageMagick compile in the archive? Is it standard or something cooked up specially for imwri? Is it Q32 or Q16? Reading your 'output is now float, I think' I think it's Q32, but want to be sure :).
If the build is Q32 / float / HDRI, what does that mean for 16 bit tiff output or DPX files and such. Impossible now?
Myrsloik
31st January 2016, 00:22
So, imwri can now be compiled against a Q32 or a Q16 ImageMagick, and it becomes 'imwrif' or 'imwri' namespace depending on which library it is compiled again?
Or it supports both Q16 and Q32 at the same time and you need to use the appropriate namespace?
If the first case is true, what version is included in test7? The files are way different than previous ImageMagick builds. Is that a new 'condensed all in one' ImageMagick compile in the archive? Is it standard or something cooked up specially for imwri? Is it Q32 or Q16? Reading your 'output is now float, I think' I think it's Q32, but want to be sure :).
If the build is Q32 / float / HDRI, what does that mean for 16 bit tiff output or DPX files and such. Impossible now?
QXX is different. The imwrif depends on HDRI (aka make everything floating point in imagemagick). Test7 is Q16 WITH HDRI so float stuff will work too. It makes no sense but that's the way it is. But the namespace is imwri because it was compiled before I changed my mind.
The QXX won't change anything apart from possible max output integer bitdepth. But in practice I'd say only Q16 and Q16 HDRI are worth to bother with.
Don't expect amalgamations because ImageMagick is shit. And a mess.
And to answer your question: HDRI=>always float output
dipje
31st January 2016, 14:26
So it is still a Q16 build like it was before, and I can still output 16 bit DPX or TIFF files like before... but the internal precision in the ImageMagick build is float so that it can do HDRI stuff on HDRI supported formats. For the other formats no change?
(Well I guess there is some sort of internal float -> 16bit integer conversion / dithering going on but that's OK).
Myrsloik
31st January 2016, 14:31
So it is still a Q16 build like it was before, and I can still output 16 bit DPX or TIFF files like before... but the internal precision in the ImageMagick build is float so that it can do HDRI stuff on HDRI supported formats. For the other formats no change?
(Well I guess there is some sort of internal float -> 16bit integer conversion / dithering going on but that's OK).
Probably no change. I guess. I'm not an ImageMagick expert.
shader
5th February 2016, 16:10
First of all: Thanks Myrsloik and all others for that great software. I like frame processing and Python. Great!
But I have a problem...
When I use Test7, unfortunatelly I can't load a sequence of files anymore.
Test6:
import vapoursynth as vs
core = vs.get_core()
core.std.LoadPlugin(path='C:/Program Files (x86)/VapourSynth/plugins32/imwri6/imwri.dll')
v = core.imwri.Read( filename=r"d:/test/%d.png", firstnum=1001)
v.set_output()
==> ok
Test7 with wildcard:
import vapoursynth as vs
core = vs.get_core()
core.std.LoadPlugin(path='C:/Program Files (x86)/VapourSynth/plugins32/imwri7/libimwri.dll')
v = core.imwri.Read( filename=r"d:/test/%d.png", firstnum=1001)
v.set_output()
==> not ok :(, "Read: No files matching the given pattern exist"
but Test7 without wildcard:
import vapoursynth as vs
core = vs.get_core()
core.std.LoadPlugin(path='C:/Program Files (x86)/VapourSynth/plugins32/imwri7/libimwri.dll')
v = core.imwri.Read( filename=r"d:/test/1001.png")
v.set_output()
==> ok
Does anybody see this problem? Or are wildcards working for anybody else?
Thanks!!!
Myrsloik
5th February 2016, 16:17
This will be investigated. Definitely should work. As a workaround you can create a list of all individual files using python and pass that. I think.
shader
6th February 2016, 17:36
Thanks and good luck!
mawen1250
25th February 2016, 11:14
files = ['{:0>3}.bmp'.format(i) for i in range(91)]
clip = core.imwri.Read(files, mismatch=True)
I tried using imwri test7 to read a list of RGB24 bmp files and found that the output format is not RGBS but RGB96 (32-bit integer).
As far as I know, none of the VapourSynth plugins supports 32-bit integer, including zimg and fmtconv, so I can do nothing with the output clip...
EDIT: tried reading a single file and the output is RGBS.
sneaker_ger
1st May 2016, 13:35
vspipe crashes when trying to open an exr file.
import vapoursynth as vs
core = vs.get_core()
ret = core.imwri.Read("0001.exr")
ret.set_output()
http://distribution.bbb3d.renderfarming.net/video/exr/1114/0001.exr
imwri "test7" build
VS R32 64 bit on Windows 7
jackoneill
3rd May 2016, 13:29
vspipe crashes when trying to open an exr file.
import vapoursynth as vs
core = vs.get_core()
ret = core.imwri.Read("0001.exr")
ret.set_output()
http://distribution.bbb3d.renderfarming.net/video/exr/1114/0001.exr
imwri "test7" build
VS R32 64 bit on Windows 7
http://ulozto.net/x7jRBqpB/imwri-r31-win64-7z
Does it still crash with this one? The namespace will be "imwrif".
sneaker_ger
3rd May 2016, 13:49
Behaves exactly the same. Even "imwrif" does not exist, only "imwri".
jackoneill
3rd May 2016, 14:25
Behaves exactly the same. Even "imwrif" does not exist, only "imwri".
Hmm, indeed. Anyway, I compiled it again. This time it's definitely "imwrif".
http://ulozto.net/xTaV1SY2/imwri-r32-win64-7z
Does it crash when you pass --info to vspipe or just when you make it output the clip?
Users of ImageMagick (also indirectly by image conversion services, especially when available via web) shall close security holes immediately:
ImageTragick (https://imagetragick.com/)
sneaker_ger
4th May 2016, 10:13
Hmm, indeed. Anyway, I compiled it again. This time it's definitely "imwrif".
http://ulozto.net/xTaV1SY2/imwri-r32-win64-7z
Does it crash when you pass --info to vspipe or just when you make it output the clip?
That version crashes as well. --info is enough to make it crash. Says "NULL passed to getPluginPath".
jackoneill
4th May 2016, 12:22
That version crashes as well. --info is enough to make it crash. Says "NULL passed to getPluginPath".
Oops. That was a small bug unrelated to your original crash. Fixed in this one: http://ulozto.net/xP4Ldykd/imwri-r32-win64-7z
sneaker_ger
4th May 2016, 12:30
Crashes with exr (but works with e.g. png).
jackoneill
8th June 2016, 13:52
When I use Test7, unfortunatelly I can't load a sequence of files anymore.
Test7 with wildcard:
import vapoursynth as vs
core = vs.get_core()
core.std.LoadPlugin(path='C:/Program Files (x86)/VapourSynth/plugins32/imwri7/libimwri.dll')
v = core.imwri.Read( filename=r"d:/test/%d.png", firstnum=1001)
v.set_output()
==> not ok :(, "Read: No files matching the given pattern exist"
Thanks!!!
Wildcards should work again:
https://ulozto.net/xaWaZ5NM/imwri-wildcards-win32-7z
https://ulozto.net/x9zryeNx/imwri-wildcards-win64-7z
shader
10th June 2016, 20:50
Thanks a lot!!!!!
It's working well and just one dll remained!
jmac698
12th June 2016, 08:05
Does it read 16 bit TIFFs? Or even RAW files (*.cr2)? That would be amazing, immedately solving some plans I have for raw processing (like median denoising)
Keiyakusha
16th June 2016, 15:31
With this plugin, is it possible to read:
a) 16bit PNG sequence into RGB48 video?
b) 4:2:0 JPEG sequence into YV12 video? (same for other variants of subsampling)
If I am reading 16bit PNG sequence into RGBS video, will fmtc.bitdepth(clip, bits=16) produce RGB48 output identical to the case a) ? If not, is there a function that will?
Myrsloik
16th June 2016, 15:39
With this plugin, is it possible to read:
a) 16bit PNG sequence into RGB48 video?
b) 4:2:0 JPEG sequence into YV12 video? (same for other variants of subsampling)
If I am reading 16bit PNG sequence into RGBS video, will fmtc.bitdepth(clip, bits=16) produce output identical to the case a) ? If not, is there a function that will?
a) If you compile the plugin against a Q16 imagemagick (Without HDRI), yes, that's what should happen.
b) No yuv output support because imagemagick hates stuff like that. You'll always get rgb. But FFMS2 should decode it properly to YUV.
If you use round to nearest in the conversion, yes, since 32 bit float can accurately represent it.
Not actually tested but that's what I expect.
Keiyakusha
16th June 2016, 16:24
a) If you compile the plugin against a Q16 imagemagick (Without HDRI), yes, that's what should happen.
b) No yuv output support because imagemagick hates stuff like that. You'll always get rgb. But FFMS2 should decode it properly to YUV.
If you use round to nearest in the conversion, yes, since 32 bit float can accurately represent it.
Not actually tested but that's what I expect.
Sounds good, thanks! I'll do some tests when I'll have time then.
dipje
18th June 2016, 20:00
... But FFMS2 should decode it properly to YUV....
FFMS2 handles image sequences? I tried something like %04d in the filename once and it didn't like it (Vapoursynth plugin that is). Was I trying it wrong?
Myrsloik
18th June 2016, 20:09
FFMS2 handles image sequences? I tried something like %04d in the filename once and it didn't like it (Vapoursynth plugin that is). Was I trying it wrong?
It doesn't handle it so you'll have to use some python code to get around it.
dipje
18th June 2016, 20:52
d'oh.. that's me coming from the avisynth era. Never thought of using python itself for problems like this :).
dipje
20th June 2016, 12:10
'It' seems to crash when loading a single DPX file (Created by ffmpeg IIRC).
Vapoursynth-editor shows something in RGB30 (which is correct) but crashes, 'vspipe -i' also crashes. Probably some fault in ffms2 I guess.
poisondeathray
6th January 2017, 19:21
FFMS2 handles image sequences? I tried something like %04d in the filename once and it didn't like it (Vapoursynth plugin that is). Was I trying it wrong?
It doesn't handle it so you'll have to use some python code to get around it.
Can you post an example of using python to load and image sequence with ffms2 please, for a python newbie
Myrsloik
7th January 2017, 22:08
Can you post an example of using python to load and image sequence with ffms2 please, for a python newbie
Sure can. Enjoy this beauty of scripting:
import vapoursynth as vs
first_image = 4
num_images = 160
filename_pattern = 'D:/imgseq/output_{0:05d}.jpg'
c = vs.get_core()
placeholder_clip = c.std.BlankClip(clip=c.ffms2.Source(filename_pattern.format(first_image), cache=False), length=num_images)
def image_loader(n):
return c.ffms2.Source(filename_pattern.format(n + first_image), cache=False)[0]
clip = c.std.FrameEval(placeholder_clip, image_loader)
clip.set_output()
The roundabout way of doing it is to avoid having a gazillion ffms2 instances created at once.
poisondeathray
8th January 2017, 02:50
Sure can. Enjoy this beauty of scripting:
import vapoursynth as vs
first_image = 4
num_images = 160
filename_pattern = 'D:/imgseq/output_{0:05d}.jpg'
c = vs.get_core()
placeholder_clip = c.std.BlankClip(clip=c.ffms2.Source(filename_pattern.format(first_image), cache=False), length=num_images)
def image_loader(n):
return c.ffms2.Source(filename_pattern.format(n + first_image), cache=False)[0]
clip = c.std.FrameEval(placeholder_clip, image_loader)
clip.set_output()
The roundabout way of doing it is to avoid having a gazillion ffms2 instances created at once.
It works nicely, thanks
Seek latency is a bit high, but I'm not complaining.
Sometimes the vpy imagemagick plugin has problems with some formats and it's a nice alternative just in case
Tormaid
15th February 2017, 02:15
What exactly is the "mismatch" option supposed to do? VS always crashes for me when I have an output with varying dimensions when mismatch is set to "True."
jackoneill
15th February 2017, 13:04
What exactly is the "mismatch" option supposed to do? VS always crashes for me when I have an output with varying dimensions when mismatch is set to "True."
From the documentation (http://www.vapoursynth.com/doc/plugins/imwri.html):
mismatch
Allow reading of multiple images with different resolutions. If required and not set, an error will be generated.
Tell me about this crash.
Tormaid
16th February 2017, 01:04
I'm aware what it is supposed to do, but I don't know how it does it. It seems like Vapoursynth does not support frame sequences with mismatched resolutions, so is mismatch=True just padding the edges to match those of the largest image?
Tell me about this crash.
Here is my script:
import vapoursynth as vs
core = vs.get_core()
v = core.imwrif.Read(r'%03d.jpg', firstnum=1, mismatch=True, alpha=False)
v.set_output()
This was crashing Vapoursynth Editor, so I thought it might be a problem with that program, but when I tried calling up the script though vspipe, I got the following error, "Cannot output clips with varying dimensions."
I ended up just writing a Photoshop script to add padding, but I would like to figure this out, as it is a nice quality-of-life feature.
jackoneill
16th February 2017, 13:39
I'm aware what it is supposed to do, but I don't know how it does it. It seems like Vapoursynth does not support frame sequences with mismatched resolutions, so is mismatch=True just padding the edges to match those of the largest image?
Here is my script:
import vapoursynth as vs
core = vs.get_core()
v = core.imwrif.Read(r'%03d.jpg', firstnum=1, mismatch=True, alpha=False)
v.set_output()
This was crashing Vapoursynth Editor, so I thought it might be a problem with that program, but when I tried calling up the script though vspipe, I got the following error, "Cannot output clips with varying dimensions."
I ended up just writing a Photoshop script to add padding, but I would like to figure this out, as it is a nice quality-of-life feature.
You can have a clip with varying resolutions. A clip like that will have 0 width and height. That's all "mismatch" does: it sets the clip's width and height to 0. Frames are not padded in any way.
It's possible that vsedit was not tested with such clips. To see if your script crashes outside vsedit you'll need to use the Python function get_frame:
for i in range(v.num_frames):
v.get_frame(i)
Run your script with Python:
python3.exe script.py
If it doesn't crash, recreate the crash using two BlankClips (and no Imwri) and complain about it to the author of vsedit.
Tormaid
8th March 2017, 18:28
You can have a clip with varying
It's possible that vsedit was not tested with such clips. To see if your script crashes outside vsedit you'll need to use the Python function get_frame:
for i in range(v.num_frames):
v.get_frame(i)
Run your script with Python:
python3.exe script.py
If it doesn't crash, recreate the crash using two BlankClips (and no Imwri) and complain about it to the author of vsedit.
Sorry for the long delay there. So, I pulled it up in Python like this and it didn't crash, just continued to process as (I assume) it jumps around to random frames.
Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> "C:\\Users\\tormaid\\Desktop\\test script.vpy"
'C:\\Users\\tormaid\\Desktop\\test script.vpy'
>>> for i in range(v.num_frames): v.get_frame(i)
...
So, assuming I did that test right, I guess I'll report this issue to the developer of Vapoursynth Editor, but I am curious as to why it crashes vspipe too.
jackoneill
10th March 2017, 21:06
Sorry for the long delay there. So, I pulled it up in Python like this and it didn't crash, just continued to process as (I assume) it jumps around to random frames.
Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> "C:\\Users\\tormaid\\Desktop\\test script.vpy"
'C:\\Users\\tormaid\\Desktop\\test script.vpy'
>>> for i in range(v.num_frames): v.get_frame(i)
...
So, assuming I did that test right, I guess I'll report this issue to the developer of Vapoursynth Editor, but I am curious as to why it crashes vspipe too.
Are you sure it's running the loop? Those three dots on the last line look like Python's waiting for you to type more.
Tormaid
26th March 2017, 21:23
Are you sure it's running the loop? Those three dots on the last line look like Python's waiting for you to type more.
I must just be doing something really stupid because I don't know why it's waiting for more input. Is there a run command I'm missing? I loaded up just the script with just the imwrif.Read() and v.set_output() commands in it and then ran the python code you gave me, and it just gave me the three dots.
TheFluff
26th March 2017, 23:49
Does it become any clearer if I write it like this instead?
for i in range(v.num_frames):
v.get_frame(i)
Or, perhaps:
>>> if True:
... print "hi"
... print "and hello"
...
hi
and hello
Remember, Python does not use curly braces ( { and } ) to open and close blocks like C-like languages do. In the Python REPL (the interactive code editor you're using), if you start a block (which you do with a colon) you can continue typing more code into that block by just hitting enter to start a new line - the interpreter tells you this is happening by replacing the regular ">>>" prompt with one that reads "...". The code will only get executed once you terminate the block, which you do by entering a blank new line.
tl;dr: press enter one more time
jackoneill
25th May 2017, 13:16
vspipe crashes when trying to open an exr file.
import vapoursynth as vs
core = vs.get_core()
ret = core.imwri.Read("0001.exr")
ret.set_output()
http://distribution.bbb3d.renderfarming.net/video/exr/1114/0001.exr
imwri "test7" build
VS R32 64 bit on Windows 7
This will be finally fixed in the next set of DLLs. The problem was in Openexr. It was caused by a mistake in a patch required to make it cross-compile.
Myrsloik
25th May 2017, 13:33
Here's test8 (https://dl.dropboxusercontent.com/u/73468194/imwri_test8.7z).
It's the first version after switching to imagemagick7 so behavior may have changed a bit. I guess.
sneaker_ger
25th May 2017, 22:46
Thx. Can confirm the crash is fixed.
george84
9th July 2017, 17:16
Thank you everyone for vapoursynth. I have very large AVIsynth scripts (up to 1M characters, generated automatically). They are used to make Slideshows. Everything works fine even up to 4K resolution.
Now I want to use 10bit BT.2020 colors and evaluate vapoursynth. I am stuck with converting jpegs to YUV.
x = core.imwrif.Read("C:/Users/Walter/Documents/SMIL/BSG23/testsuite/OLED/colorcheckerchart.jpg", firstnum=0, mismatch=False, alpha=False)
#x = core.ffms2.Source(source='C:/Users/Walter/Documents/SMIL/BSG23/testsuite/OLED/colorcheckerchart.jpg')
x = fAVSimgExtend(x, 240)
SMILregion1 = core.resize.Point(x, format=vs.YUV420P10, primaries = 1, transfer_s = "709", transfer_in_s = "709", matrix_s="709", range_s = "full")
The above code sequence crashes VS Editor when doing preview because of primaries=1 in resize. (only primaries=2 will work)
Crash happens when reading jpef with imwrif as well as with ffms2. I used TEST8 for imwrif and have vapoursynth R38, 32 bit on Windows10.
What is the correct resize statement to convert an RGB (assume BT.2020 colorspace, not sRGB) to HDR10. Matrix, Transfer and primaries?
Myrsloik
11th July 2017, 11:30
I'll try to reproduce this in a day or two. It definitely shouldn't be crashing...
Thank you everyone for vapoursynth. I have very large AVIsynth scripts (up to 1M characters, generated automatically). They are used to make Slideshows. Everything works fine even up to 4K resolution.
Now I want to use 10bit BT.2020 colors and evaluate vapoursynth. I am stuck with converting jpegs to YUV.
x = core.imwrif.Read("C:/Users/Walter/Documents/SMIL/BSG23/testsuite/OLED/colorcheckerchart.jpg", firstnum=0, mismatch=False, alpha=False)
#x = core.ffms2.Source(source='C:/Users/Walter/Documents/SMIL/BSG23/testsuite/OLED/colorcheckerchart.jpg')
x = fAVSimgExtend(x, 240)
SMILregion1 = core.resize.Point(x, format=vs.YUV420P10, primaries = 1, transfer_s = "709", transfer_in_s = "709", matrix_s="709", range_s = "full")
The above code sequence crashes VS Editor when doing preview because of in . (only will work)
Crash happens when reading jpef with imwrif as well as with ffms2. I used for imwrif and have vapoursynth R38, 32 bit on Windows10.
What is the correct resize statement to convert an RGB (assume BT.2020 colorspace, not sRGB) to HDR10. Matrix, Transfer and primaries?
I don't have an hdr or bt2020 monitor so I can't test my code.
Assuming a standard srgb jpeg
jpeg to bt2020 10bit NOT HDR
ffms2 open the jpeg as yuv
import vapoursynth as vs
core = vs.get_core()
c = core.ffms2.Source(source = 'C:/Users/...')
c=core.resize.Bicubic(clip=c, format=vs.RGB48, filter_param_a=0, filter_param_b=0.75, matrix_in_s="470bg", range_in_s="full", range_s="full", chromaloc_in_s="center", dither_type="none")
c=core.resize.Bicubic(clip=c, format=vs.RGB48, transfer_in_s="709", transfer_s="linear")
c=core.resize.Bicubic(clip=c, format=vs.RGB48, primaries_in_s="709", primaries_s="2020")
c=core.resize.Bicubic(clip=c, format=vs.RGB48, transfer_in_s="linear", transfer_s="2020_10")
c=core.resize.Bicubic(clip=c, format=vs.YUV420P10, filter_param_a=0.0,filter_param_b=0.75, matrix_s="2020ncl", range_in_s="full", range_s="limited")
imwri open the jpeg as rgb
import vapoursynth as vs
core = vs.get_core()
c = core.imwri.Read(filename='C:/....')
c=core.resize.Bicubic(clip=c, format=vs.RGB48, transfer_in_s="709", transfer_s="linear")
c=core.resize.Bicubic(clip=c, format=vs.RGB48, primaries_in_s="709", primaries_s="2020")
c=core.resize.Bicubic(clip=c, format=vs.RGB48, transfer_in_s="linear", transfer_s="2020_10")
c=core.resize.Bicubic(clip=c, format=vs.YUV420P10, filter_param_a=0.0,filter_param_b=0.75, matrix_s="2020ncl", range_in_s="full", range_s="limited")
rgb bt2020 to HDR10 1000 nits yuv
c=core.resize.Bicubic(clip=c, format=vs.RGB48, transfer_in_s="2020_10", transfer_s="linear")
c=core.resize.Bicubic(clip=c, format=vs.RGB48, transfer_in_s="linear", transfer_s="st2084", nominal_luminance=1000)
c=core.resize.Bicubic(clip=c, format=vs.YUV420P10, filter_param_a=0.0,filter_param_b=0.75, matrix_s="2020ncl", range_in_s="full", range_s="limited")
george84
12th July 2017, 08:25
Thank you @age.
I have an OLED TV which supports HDR10. It will take me some time to test and understand your solution.
Currently I have two solutions which don't look too bad:
Option 1:
Read JPG in avisynth to YV12 and pipe to FFMPEG and then to X265. In FFMPEG I do
zscale=p=2020:t=smpte2084:m=2020_ncl:pin=709:tin=709:min=709" -pix_fmt yuv420p10
Option 2:
Read JPG in vapoursynth to RGB and do
x = core.resize.Point(x, format=vs.YUV420P10,
primaries = 9, primaries_in =1,
transfer_s = "st2084", transfer_in_s = "709",
matrix_s = "2020ncl",matrix_in_s = "rgb",
range_s = "full", range_in_s = "full")
For both options things look good on TV, but not really better than a normal HDR encoding (I assume TV does a quite good upscale of HDR to HDR10). I am aware that jpg is only 8 bits and have no real BT.2020 source. To overcome this I will try to convert 14bit DNG to 10bit tiff
Thank you @age.
I have an OLED TV which supports HDR10. It will take me some time to test and understand your solution.
Currently I have two solutions which don't look too bad:
Option 1:
Read JPG in avisynth to YV12 and pipe to FFMPEG and then to X265. In FFMPEG I do
Option 2:
Read JPG in vapoursynth to RGB and do
For both options things look good on TV, but not really better than a normal HDR encoding (I assume TV does a quite good upscale of HDR to HDR10). I am aware that jpg is only 8 bits and have no real BT.2020 source. To overcome this I will try to convert 14bit DNG to 10bit tiff
You could play with the nominal_luminance parameter, if not set it is equal to 100(nits) so it is HDR10 100 nits.
#c=core.resize.Bicubic(clip=c, format=vs.RGB48, filter_param_a=0, filter_param_b=0.75, matrix_in_s="470bg", range_in_s="full", range_s="full", chromaloc_in_s="center")#jpeg to rgb
c=core.resize.Bicubic(clip=c, format=vs.YUV420P10, filter_param_a=0.0,filter_param_b=0.75, matrix_in_s="rgb",matrix_s="2020ncl",primaries_in_s="709",primaries_s="2020", transfer_in_s="709", transfer_s="st2084", range_in_s="full", range_s="limited", nominal_luminance=1000)
I prefer to use bicubic 75 for chroma resize :-)
george84
12th July 2017, 11:52
You could play with the nominal_luminance parameter, if not set it is equal to 100(nits) so it is HDR10 100 nits.
I tried out your code with sRGB jpeg source. The good news is, that both versions (read with imwrif, and read with ffms2) give identical results.
But on TV the colors are too vivid. There is no contrast in bright spots. When I replace transfer function "2020_10" with "st2084" it looks better. My encoding is:
"C:\Program Files (x86)\VapourSynth\core32\vspipe" --y4m v1.vpy - | "C:\Users\Walter\Downloads\ffmpeg-20170605-4705edb-win32-static\bin\ffmpeg.exe" -nostats -i pipe: -strict -1 -r 24 -f yuv4mpegpipe - | "x265_x64_10bit.exe" - --y4m --bitrate 40000 --input-csp 1 --level-idc 5.1 --no-open-gop --hdr --aud --hrd --hdr-opt --colorprim bt2020 --transfer smpte-st-2084 --colormatrix bt2020nc --master-display "G(13250,34500)B(7500,3000)R(34000,16000)WP(15635,16450)L(10000000,500)" --max-cll "1000,400" --output "v4.hevc"
PAUSE
muxer -i v4.hevc -o v4.mp4
del v4.hevc
PAUSE
In HDR10 specs they say transfer function is ST2084. How can I vary this nominal luminance parameter?
george84
12th July 2017, 12:34
When I encode a colorchart test image then I get:
with 2020_10 transfer function for Luminance Y values between 64 and 940
with st2084 transfer function for Luminance Y values between 64 and 509
according to https://art-drivers.net/understanding-hdr/the_hdr_cheat_sheet/ I should get a maximum of about Y=700 because my display has a peak luminance of about 650nits.
So the question is really how to vary this. I try with Levels filter.
the values in https://art-drivers.net/understanding-hdr/the_hdr_cheat_sheet/
are in standard yuv limited range.
You can vary Y with
transfer_s="st2084",nominal_luminance=
Have you tried?
c=core.resize.Bicubic(clip=c, format=vs.YUV420P10, filter_param_a=0.0,filter_param_b=0.75, matrix_in_s="rgb",matrix_s="2020ncl",primaries_in_s="709",primaries_s="2020", transfer_in_s="709", transfer_s="st2084", range_in_s="full", range_s="limited", nominal_luminance=1000)
hdr10 generally is 1000 nits,nominal_luminance=1000, transfer_s="st2084"
your monitor has a peak luminance of about 650nits so you could use nominal_luminance=650, transfer_s="st2084"
c=core.resize.Bicubic(clip=c, format=vs.YUV420P10, filter_param_a=0.0,filter_param_b=0.75, matrix_in_s="rgb",matrix_s="2020ncl",primaries_in_s="709",primaries_s="2020", transfer_in_s="709", transfer_s="st2084", range_in_s="full", range_s="limited", nominal_luminance=650)
Black level for hdr10 is 64 (10 bit) because the full to limited range conversion
HDR10: Nominal Black for 10-bit at 64
george84
12th July 2017, 18:59
Thank you for this hint. As I understand I could also use nominal_luminance in x265 zscale as npl parameter.
I tried in vapoursynth and found that default of 100 is almost too bright. In TV I have three picture settings for HDR (vivid, bright, standard). Best quality is when I set npl=50 and use vivid setting. Of course the TV is not calibrated.
What I don't understand is why the white in jpeg does not become white on TV. I attach a screenshot of vapoursynth preview. You see that the clip info, which I added immediately after resize with x=x.text.ClipInfo() has real white (Y=940) and real black (Y=64). But the white of jpeg is Y=509 and the black is Y=64. (this was with npl=100)
@george84
Post your script because there could be some errors.
I think you really should not use nominal_luminance=100 (100nits), because 100nits is SDR and of course it looks bad with an HDR picture style.
PS. Maybe it's better to open a new topic for this discussion "sdr to hdr"
poisondeathray
25th August 2017, 17:03
Is there a way that you can prevent writing an alpha channel with imwrif.Write ? I tried alpha=None , alpha=False but no luck
If internally there is no alpha channel , the plugin seems to write a "dummy" one anyways
Myrsloik
25th August 2017, 17:05
Is there a way that you can prevent writing an alpha channel with imwrif.Write ? I tried alpha=None , alpha=False but no luck
If internally there is no alpha channel , the plugin seems to write a "dummy" one anyways
No, probably not then. Imagemagick doesn't really document how it determines when to write an alpha channel.
poisondeathray
25th August 2017, 17:39
Were you still investigating IM alternatives ?
What about OpenImageIO ? It's used in open software such as blender, natron ; and commercial software as well . Quite active development
https://sites.google.com/site/openimageio/home
https://github.com/OpenImageIO/oiio
Myrsloik
25th August 2017, 22:31
Were you still investigating IM alternatives ?
What about OpenImageIO ? It's used in open software such as blender, natron ; and commercial software as well . Quite active development
https://sites.google.com/site/openimageio/home
https://github.com/OpenImageIO/oiio
I shall add it to my list of things to look at. Could be interesting if the api isn't shit.
Myrsloik
21st September 2017, 11:29
Download link updated. Dropbox seems to have randomly broken some of my older links.
poisondeathray
11th October 2017, 05:37
Current namespace for test8 is imwrif, but documentation says imwri ; can you update the documentation if it's going to stay that way
Myrsloik
11th October 2017, 09:54
Current namespace for test8 is imwrif, but documentation says imwri ; can you update the documentation if it's going to stay that way
It depends on how the imagemagick library was compiled. Also don't stop reading the documentation after the first line.
Myrsloik
21st December 2017, 22:00
Is there a way that you can prevent writing an alpha channel with imwrif.Write ? I tried alpha=None , alpha=False but no luck
If internally there is no alpha channel , the plugin seems to write a "dummy" one anyways
I looked at this and tried to improve it. What's the format you tried it with? Alpha in the output seems to mostly depend on which format you specify in the formatstring. Like PNG24 or 32. I think. I've made some changes that should at least not set the alpha at all now but most formats still write it.
poisondeathray
21st December 2017, 22:37
I looked at this and tried to improve it. What's the format you tried it with? Alpha in the output seems to mostly depend on which format you specify in the formatstring. Like PNG24 or 32. I think. I've made some changes that should at least not set the alpha at all now but most formats still write it.
IIRC, I think it was a DPX sequence that lead me to post, but I confirmed it with a PNG export too . Typically DPX shouldn't have an alpha channel and it "confused" some other programs on import
Myrsloik
21st December 2017, 23:01
IIRC, I think it was a DPX sequence that lead me to post, but I confirmed it with a PNG export too . Typically DPX shouldn't have an alpha channel and it "confused" some other programs on import
I think I found the main issue. No more alpha written unless an alpha clip is specified. If you compile things yourself you can test it. I also fixed a lot of the bitdepth mess and removed the need for two versions so expect a new build soon.
poisondeathray
21st December 2017, 23:09
I think I found the main issue. No more alpha written unless an alpha clip is specified. If you compile things yourself you can test it. I also fixed a lot of the bitdepth mess and removed the need for two versions so expect a new build soon.
Ok thanks. I'll test when the official build comes out
Myrsloik
22nd December 2017, 19:44
Test 9 added to first post. Try it and see how it works. Namespace is now always imwri.
poisondeathray
22nd December 2017, 20:41
vapoursynth R41 x64 test 2 / imwri r41 x64 test9
Just a quick test, I'll try some more things later
It doesn't seem to load a regular PNG, with or without alpha, or even a JPG. vsedit reports RGB24, correct dimensions, but it's black screen in vapoursynth editor . Is it a compatiblity issue with vsedit ? I tried converting to COMPATBGR32 still not working. But no error messages, just black screen.
Swapping out back to imwri test 8 (and using imwrif) works fine under R41 x64 test 2 to load a basic PNG or JPG , so it doesn't seem to be a vapoursynth R41 test 2 issue . Other than the namespace, was there some other syntax changes to the plugin ?
Myrsloik
25th December 2017, 20:49
It's probably miscompiled then. Happens now and then with imagemagick stuff, especially since producing a single monolithic dll requires evil mingw stuff. Will make another attempt.
Myrsloik
28th December 2017, 13:56
vapoursynth R41 x64 test 2 / imwri r41 x64 test9
Just a quick test, I'll try some more things later
It doesn't seem to load a regular PNG, with or without alpha, or even a JPG. vsedit reports RGB24, correct dimensions, but it's black screen in vapoursynth editor . Is it a compatiblity issue with vsedit ? I tried converting to COMPATBGR32 still not working. But no error messages, just black screen.
Swapping out back to imwri test 8 (and using imwrif) works fine under R41 x64 test 2 to load a basic PNG or JPG , so it doesn't seem to be a vapoursynth R41 test 2 issue . Other than the namespace, was there some other syntax changes to the plugin ?
I tested it and it does work well here with the images I tried. You're doing it wrong (probably). Give it another try.
poisondeathray
28th December 2017, 16:58
I tested it and it does work well here with the images I tried. You're doing it wrong (probably). Give it another try.
I have more faith in your testing, but still the same results. I don't see how I'm doing it wrong when it works with test8
I upgraded to Vapoursynth x64 R41 test 4, downloaded plugin again in case it was corrupt, upgraded VSEdit to R18, still doesn't work
The same source image works with imwri_test8 , or other source filters like ffms2 etc... so it's not a source issue and VSEdit is working correctly
I used the correct namespace, tried the wrong namespace, tried different arrays , Alpha=True vs False
Again, it's just a black screen. It reports everything else correctly, dimensions, etc... and Gray8 when returning the alpha [1], or RGB24 when returning [0]
Myrsloik
28th December 2017, 16:59
I have more faith in your testing, but still the same results. I don't see how I'm doing it wrong when it works with test8
I upgraded to R41 test 4, downloaded plugin again in case it was corrupt, upgraded VSEdit to R18, still doesn't work
The same source image works with imwri_test8 , or other source filters like ffms2 etc... so it's not a source issue
I used the correct namespace, tried the wrong namespace, tried different arrays , Alpha=True vs False
Can I have one of the not working images? Maybe it's something broken in the latest imagemagick...
poisondeathray
28th December 2017, 17:04
Can I have one of the not working images? Maybe it's something broken in the latest imagemagick...
It's a super simple alpha channel test 1280x720 8bit RGBA png
http://www.mediafire.com/file/8pr2lx962cmxc5c/logo.png
Myrsloik
28th December 2017, 17:22
It's a super simple alpha channel test 1280x720 8bit RGBA png
http://www.mediafire.com/file/8pr2lx962cmxc5c/logo.png
Doh, I only tested with high bitdepth images. A bug in how the output scaling is calculated made all below 16 bit images black.
Myrsloik
28th December 2017, 17:49
Download test9 again. It's been updated.
poisondeathray
28th December 2017, 17:54
Download test9 again. It's been updated.
This works now, but the alpha returned on that simple test is messed up. It's like an edge outline/mask
Myrsloik
28th December 2017, 18:30
This works now, but the alpha returned on that simple test is messed up. It's like an edge outline/mask
Sigh, found the reason for that too now. Can you test writing with this build as well?
poisondeathray
28th December 2017, 20:15
yes, I have time to test out a bunch of things, formats, read/write , bitdepths in the next few days.
But I stumbled on step 1 with a simple 8bit png :)
Is the next build up ?
Myrsloik
28th December 2017, 20:42
yes, I have time to test out a bunch of things, formats, read/write , bitdepths in the next few days.
But I stumbled on step 1 with a simple 8bit png :)
Is the next build up ?
Yes, updated the links again.
poisondeathray
29th December 2017, 02:51
The reader seems to be working well with different common image formats & compressions
-Instead of importing higher bit depth formats automatically as RGBS , it seems to get it correct now (e.g. 16bit RGB PNG would be RGB48 instead of RGBS like before).
-Alpha channel working too.
-(not related to IM, but linear to sRGB for linear image types using the internal VS resize is working correct)
1) EXR float is still imported as RGB48 instead of RGBS, and EXR halffloat is also imported as RGB48 instead of RGBH. But if I'm not mistaken, these are an imagemagick limitation ?
The writer works (abeit slowly), including sequence writing;
2) but imwri does not seem write out high bit depth , or at least I couldn't find the correct switch.
eg. 10bit RGB30 with core.imwri.Write, exporting DPX will write as 8bit
eg. 16bit RGB48 with core.imwri.Write, exporting PNG will write as 8bit
I tried imwrif (instead of imwri), and the docs say
Note that the namespace will be imwrif when compiled with a HDRI ImageMagick to distinguish the behavior and accepted format input/output formats.
yet, this one reads high (and low) bit depth formats, I just can't "convince" it to export high
Myrsloik
30th December 2017, 19:45
I updated the links again. This time it's tested. Mostly with tiff output but I fixed a pile of issues in the writing logic. There's also a float_output argument to force float format when reading images.
If you have a half precision float tiff file that'd be great too. It's the last rare thing I need for my testing. An interesting observation is that imagemagick itself only seems to properly flag that the source file is floating point for tiff, miff and mat. So unless float_output is set all other 16 bit images will be output as integer.
poisondeathray
30th December 2017, 21:09
I updated the links again. This time it's tested. Mostly with tiff output but I fixed a pile of issues in the writing logic. There's also a float_output argument to force float format when reading images.
If you have a half precision float tiff file that'd be great too. It's the last rare thing I need for my testing. An interesting observation is that imagemagick itself only seems to properly flag that the source file is floating point for tiff, miff and mat. So unless float_output is set all other 16 bit images will be output as integer.
Ok thanks I'll test the new one over the next few days
I've never seen a half float tiff, it's an rare subset.
There is an option to export it in natron, but when I use no compression , it's the same filesize as full float tiff. It makes think it's not actually half float. Most other programs don't have half float option; if they do it's only for EXR
Maybe some of the more exotic command line raw converters or some branches of imagemagick or related programs might be able to do it.
dipje
5th January 2018, 21:29
Photoshop has the option to save a floating-point image as FP32, FP24 or FP16. Filesizes when saving with no compression are correct (as in, they are all different).
I know 'the fact that Photoshop does it does not make it a standard' is always a thing :), but it does mean there is at least one high-profile bit of software there.
poisondeathray
6th January 2018, 05:39
Photoshop has the option to save a floating-point image as FP32, FP24 or FP16. Filesizes when saving with no compression are correct (as in, they are all different).
I know 'the fact that Photoshop does it does not make it a standard' is always a thing :), but it does mean there is at least one high-profile bit of software there.
Yes, you're right. How could I forget about PS ???!
exiftool reports a bunch of info and can distinguish between F32 and F16 Tiffs as well
Do you still need a samply Myrsloik ?
Myrsloik
6th January 2018, 12:29
Yes, I still want that elusive half precision tiff. I'm curious about what will happen.
poisondeathray
6th January 2018, 16:27
F16 Tiff
http://www.mediafire.com/file/a8rc4w1pdryzq7e/Bars_F16.7z
Myrsloik
6th January 2018, 22:00
F16 Tiff
http://www.mediafire.com/file/a8rc4w1pdryzq7e/Bars_F16.7z
Verified it and it's properly output as single precision float (nobody likes half precision float for later processing anyway)
poisondeathray
8th January 2018, 05:18
Will there ever be a build that has FP16/32 EXR (or TIFF I guess) export ? Or is that just not on the timeline whatsoever ?
Myrsloik
8th January 2018, 10:26
Will there ever be a build that has FP16/32 EXR (or TIFF I guess) export ? Or is that just not on the timeline whatsoever ?
You should be able to export F32 tiff right now. Not sure about which format exr will pick if you give it F32 input. F16 will probably need another option to set the number of floating point bits on output.
dipje
8th January 2018, 14:11
I did some EXR tests lately with the recent imwri sources.
1) it works (After Effects reads it just fine)
2) It 'seems' half-precision? (32bit EXR is more of an extension, right?). At least, when I export the same image-sequence again from AE without any changes, and select the same compression and half-precision, the files are pretty much the same size.
poisondeathray
8th January 2018, 18:50
1) confirmed, F32 tiff write works .
2) confirmed dipje's observations , EXR for write is F16 when using default setting (exiftool reports it as half, and can distinguish between common EXR compression formats for F16/32)
3) Not directly an imwri issue, but there seems to be a loss of precision when doing a linear<=>srgb conversion . I think it's a resize/zimg issue.
Usually float formats are linearized in other programs . So if you import an EXR, usually you need to specify the transfer parameters to delinearlize if converting to sRGB/Rec709
In F32/16, I would have expected this operation to be "reversible"
Recall this thread:
https://forum.doom9.org/showthread.php?t=174839
Recall this YUV420P10 to RGBS back to YUV420P10 is lossless
import vapoursynth as vs
core = vs.get_core()
clip = core.lsmas.LWLibavSource(r'F:\testchart720.png')
clip = core.resize.Bicubic(clip, format=vs.YUV420P10, matrix_s="709")
clip2 = core.resize.Point(clip, format=vs.RGBS, matrix_in_s="709", dither_type="none")
clip3 = core.resize.Point(clip2, format=vs.YUV420P10, matrix_s="709", dither_type="none")
d = core.std.MakeDiff(clip, clip3)
da = core.std.Levels(d, min_in=511, max_in=513, gamma=1, min_out=0, max_out=1023, planes=[0,1,2])
da.set_output()
So if you write out a non linearized TIFF or EXR it works. But most programs "expect" linear float
So adding linearization (in the attempt to write out a linear EXR or TFF F16/32) makes it non reversible or some loss . (I've omitted the write step here, but that's where I noticed the issue, and I'm working backwards to trace the issue)
import vapoursynth as vs
core = vs.get_core()
clip = core.lsmas.LWLibavSource(r'F:\testchart720.png')
clip = core.resize.Bicubic(clip, format=vs.YUV420P10, matrix_s="709")
clip2 = core.resize.Point(clip, format=vs.RGBS, matrix_in_s="709", dither_type="none", transfer_in_s="srgb", transfer_s="linear")
clip3 = core.resize.Point(clip2, format=vs.YUV420P10, matrix_s="709", dither_type="none", transfer_in_s="linear", transfer_s="srgb")
d = core.std.MakeDiff(clip, clip3)
da = core.std.Levels(d, min_in=511, max_in=513, gamma=1, min_out=0, max_out=1023, planes=[0,1,2])
da.set_output()
I've tried full range, splitting out the steps (converting to RGBS first, then specifying the transfer later instead of 1 step)
What am I missing ?
EDIT: sRGB <=> linear transfer using core.fmtc.transfer also exhibits differences
EDIT#2: But "61966-2-4" using fmtconv does not show differences for the transfer portion, and works. Must be those negative values ?
IEC 61966-2-4, xvYCC. Same as BT.709, but with an extended range, inlcuding negative values.
import vapoursynth as vs
core = vs.get_core()
clip = core.lsmas.LWLibavSource(r'F:\testchart720.png')
clip = core.resize.Bicubic(clip, format=vs.YUV420P10, matrix_s="709")
clip2 = core.resize.Point(clip, format=vs.RGBS, matrix_in_s="709", dither_type="none", range_in_s="full")
clip2a = core.fmtc.transfer(clip2, transs="61966-2-4", transd="linear")
clip2b = core.fmtc.transfer(clip2a, transs="linear", transd="61966-2-4")
clip3 = core.resize.Point(clip2b, format=vs.YUV420P10, matrix_s="709", dither_type="none", range_s="full")
d = core.std.MakeDiff(clip, clip3)
da = core.std.Levels(d, min_in=511, max_in=513, gamma=1, min_out=0, max_out=1023, planes=[0,1,2])
da.set_output()
I do not see "61966-2-4" as a valid entry for zimg/resize for transfer_s or transfer_in_s
dipje
8th January 2018, 22:49
I was testing with loading in HDR footage, and in floating point scaling it to linear light, writing it out as EXR and grade it for SDR in After Effects / Premiere.
And I discovered the same. fmtconv's transfer function clips (and it says so in the manual) which is a shame but OK. I figure that z.img (core.resize.xxx) does the same when messing with transfer_in / transfer.
converting color-primaries needs to be done in linear-light (according to fmtconv) so it's kinda a shame.
Also (unrelated to vapoursynth): If z.img transfer-conversion clips (not confirmed yet to be honest), that means that ffmpeg's tonemapping filter (which needs float and in the manual is recommended by using z.img to convert to linear-light, then the tonemap filter, then convert to your target transfer) also will have issues if you're not careful. I was expectng the float to be handy for HDr->SDR to you can map to a 'usable' brighness but with all the overbrights in the > 1.0 range, and then use tonemapping to do something with it. Apparently not :).
Myrsloik
8th January 2018, 22:49
If you use the R41 RC you can use "xvycc" as transfer. A lot of stuff was added in zimg.
poisondeathray
8th January 2018, 22:56
But the fmtconv transfer still is not quite right in other programs. Nothing is lost when you use "61966-2-4" (at least on that small test) , but the contrast black/white point has changed in other programs when using linear interpretation
zimg's looks more correct (or what you would expect) but there is some loss, it looks almost as if it was working in 16bit int, like ffmpeg's linear conversion does too. You see the loss in almost the same areas
I'll try some more tests with the newer R41RC
But none of this is the imwri plugin's fault - that appears to be working now
poisondeathray
8th January 2018, 23:20
Can you explain the problem with z.lib? When operating in fast mode (e.g. with VapourSynth), transfer conversions to/from linear are evaluated at 14-bit precision and also clipped. The API supports full-precision transfer functions, but it is dramatically slower.
The problem is as you described. The transfer portion appears to exhibit loss when dealing with linear float formats
Is there a way to access the full precision / slow mode ?
poisondeathray
8th January 2018, 23:37
VapourSynth does not expose the option to trade precision/range for speed. However, you can control this option indirectly by setting the "cpu" parameter to "none". However, from a workflow point of view, it is not clear to me why out-of-range non-linear values would be desirable. Normally one would perform all the limiting steps in the linear RGB domain, which is the output of the EXR decoder.
That is only a synthetic, simple test example
In real workflows, either with CG , Raw and HDR cameras, you have those out of range values, and the workflow is usually linear. So a transfer function that can maniuplate linear float formats would useful
Thanks for the "cpu" parameter tip , I will do some more tests later
poisondeathray
9th January 2018, 03:29
Yes, cpu_type="none" works
It's nice to have a delinearize/linearize transfer function workflow option that does not produce additional loss
The reason why you would use "transfer" in the first place is to "linearize" something to prepare it for another program. For example color manipluations ,filters. On the round trip back, you might have to "delinearize" or apply the transfer back to sRGB and eventually YUV
A typical example would be a prores acquisition from a camera. You might have to do some filtering in vapoursynth in YUV (maybe some noise reduction), then send it to some other program for color work in linear RGB. Or on the trip back, into vapoursynth to apply some other manipulations
poisondeathray
9th January 2018, 04:42
Since the fast mode for transfer functions is a LUT, z.lib has limited ability to handle out-of-range values. Would extending the coverage from [0.0,1.0] to [-0.5,1.5] (normalized, non-linear RGB) handle the out-of-range values you encounter in practice?
I would assume so, it's not something I measure regularly
Everything works with cpu_type="none", at least on a few quickie tests, but what is the typical speed penalty for "slow" mode ? I know it would vary by source, hardware setup etc.., but just ballpark estimate? I guess I could measure it too...
What would be the "cons" of implementing extended coverage range? For example would it slow down conversions that don't need it ? That would involve a more complex LUT , right ? Would it negatively impact something even when the transfer function wasn't called ?
But I would imagine someone calling the transfer function most frequently used would be sRGB <=> linear , and if you're going to be using float formats with linear workflow, the main point was probably precision in the first place... I would argue for those types of workflows you might as well go all the way
Selur
11th January 2018, 21:07
Small feature request:
Would be nice if
Read(string[] filename[, int firstnum=0, bint mismatch=False, bint alpha=False, bint float_output = False])
could also get a
int lastnum
parameter like Avisynths Image source.
Cu Selur
Myrsloik
11th January 2018, 21:09
Small feature request:
Would be nice if
Read(string[] filename[, int firstnum=0, bint mismatch=False, bint alpha=False, bint float_output = False])
could also get a
int lastnum
parameter like Avisynths Image source.
Cu Selur
What? To only read a limited number of images? But that could be solved with trim after just as easy...
LigH
11th January 2018, 21:51
Even if you could prove that it is not the case ... it may make the user feel that it takes more resources than required (first reads images it dismisses later). ;)
Selur
11th January 2018, 21:55
What? To only read a limited number of images? But that could be solved with trim after just as easy...
Okay I assumed that all the images would be scanned first and with for example an image count of 2 000 000 using 'firstnum=15' and 'clip = core.std.Trim(clip=clip, length=15691)' would be less effective,..
If not all images have to be scanned first, then I agree and trim is fine. :)
Cu Selur
Myrsloik
11th January 2018, 22:34
Okay I assumed that all the images would be scanned first and with for example an image count of 2 000 000 using 'firstnum=15' and 'clip = core.std.Trim(clip=clip, length=15691)' would be less effective,..
If not all images have to be scanned first, then I agree and trim is fine. :)
Cu Selur
The only check that's done is if the files exists so unless you have a ridiculously long sequence you should never need it. So the answer is somewhere inbetween. If you ever find a sequence that's slow I'll add it.
Selur
12th January 2018, 05:08
Okay. Thanks! :)
TheFluff
12th January 2018, 15:56
Even if you could prove that it is not the case ... it may make the user feel that it takes more resources than required (first reads images it dismisses later). ;)
Please stop disrespecting old Donald Knuth ("premature optimization is the root of all evil"). You really shouldn't encourage people to micro-optimize things based on intuition and guesswork. It's very common in Avisynth circles (c.f. the guy who wrote 3000 lines of asm to optimize bitblt with zero real-world performance improvement, the continued insistence on compiling with all kinds of completely pointless instruction sets enabled because it feels good or something, etc etc) but it's a really awful idea. Testing for the existence of 100k files takes on the order of 0.1 seconds on any reasonably modern hardware, and it's only done once.
poisondeathray
14th January 2018, 01:28
This experimental build (https://www.dropbox.com/s/m63ly0ahbtrnjjt/VapourSynth.dll?dl=0) of VapourSynth R41 preserves some BTB/WTW information when applying transfer functions. It may or may not work for you. Replace the vapoursynth.dll in the "Lib\site-packages\vapoursynth" directory of your Python installation.
Thanks!
@Myrsloik - when you get a chance, can you add EXR F32 write option ?
Myrsloik
14th January 2018, 11:07
Thanks!
@Myrsloik - when you get a chance, can you add EXR F32 write option ?
If imagemagick doesn't write it when you give it 32bit float its simply an imagemagick limitation.
feisty2
28th January 2018, 04:50
can I output floating point TIFFs?
clp = core.imwrif.Write(clp, "tiff", "%06d.tif", 0, compression_type="None")
#clp is GrayS but this gives me a Gray16 sequence
according to the imagemagick documentation (https://imagemagick.org/script/formats.php), I need to append "-define quantum:format=floating-point" in the command line, how do I do that with imwri?
poisondeathray
28th January 2018, 05:05
can I output floating point TIFFs?
clp = core.imwrif.Write(clp, "tiff", "%06d.tif", 0, compression_type="None")
#clp is GrayS but this gives me a Gray16 sequence
according to the imagemagick documentation (https://imagemagick.org/script/formats.php), I need to append "-define quantum:format=floating-point" in the command line, how do I do that with imwri?
Did you update your vapoursynth? It works here with GRAYS
It's imwri.Write now, not imwrif.Write , so you must be using older version
feisty2
28th January 2018, 05:48
Did you update your vapoursynth? It works here with GRAYS
It's imwri.Write now, not imwrif.Write , so you must be using older version
yeah I just updated to test 9 and it's working now
foxyshadis
5th March 2018, 11:22
I wouldn't normally ask for updates except that I have zero confidence in being able to set up an ImageMagick build environment, but 7.0.7.22 was released with HEIF/HEIC support recently, and it'd be a lot of fun to play around with that capability. I'm strongly leaning toward it for general purposes unless a competitor pops up from Xiph or Google soon, since JXR went nowhere.
jackoneill
5th March 2018, 16:05
I wouldn't normally ask for updates except that I have zero confidence in being able to set up an ImageMagick build environment, but 7.0.7.22 was released with HEIF/HEIC support recently, and it'd be a lot of fun to play around with that capability. I'm strongly leaning toward it for general purposes unless a competitor pops up from Xiph or Google soon, since JXR went nowhere.
Is that built into ImageMagick, or does it need an external library?
foxyshadis
6th March 2018, 03:14
Is that built into ImageMagick, or does it need an external library?
Requires libde265 be present, as an additional dependency.
jackoneill
6th March 2018, 14:04
I wouldn't normally ask for updates except that I have zero confidence in being able to set up an ImageMagick build environment, but 7.0.7.22 was released with HEIF/HEIC support recently, and it'd be a lot of fun to play around with that capability. I'm strongly leaning toward it for general purposes unless a competitor pops up from Xiph or Google soon, since JXR went nowhere.
Imwri with ImageMagick 7.0.7-25 and libde265 1.0.2 (http://savedonthe.net/download/2110/imwri-r43-win64.html)
foxyshadis
8th March 2018, 13:39
Thanks for the build. It looks like IM's current implementation has some big bugs, maybe it only works specifically with Apple's files, since its own image reader can't read the conformance files. Probably down to the MP4 parsing. I'll see if I can narrow down what's going on and get them to patch it.
Alexkral
9th April 2020, 01:00
Hi, sorry if I am not understanding how this can be used, I am new to Vapoursynth. I am trying to run this Python script on Windows through the command line:
import vapoursynth as vs
core = vs.get_core()
src = core.imwri.Read("C:/image_01.png")
src = core.imwri.Write(src, imgformat="PNG", filename="C:/image_02.png")
src.get_frame(0)
src.set_output()
This doesn't write anything to disk, as I understand this is because frames are not being required from IMWRI, so get_frame doesn't work for it. Is there a different way to do it by running a Python script through the command line?
poisondeathray
9th April 2020, 02:31
@Alexkral, see post #8,9 in this thread
https://forum.doom9.org/showthread.php?p=1885855
Alexkral
9th April 2020, 03:23
Thanks, now it works.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.