Log in

View Full Version : ImageSource(), ImageWriter(), x264-compressed still photos, avisynth improvements


turbine
5th August 2012, 08:42
YES... FINALLY I can post! The five-day waiting period is NOT a very kind policy, and definitely one that turns away contributors. I'd suggest a better solution would be requiring moderation during that period. Having said that, I appreciate this forum and its contributors. With a bit of trial and error the posts have been helpful and making sense of avisynth's impressive capabilities but cumbersome scripting format and design flaws.

I've been experimenting with using x264 to encode libraries of still images with impressive results. I'd like to share my results so far so that they may help others and assist further avisynth development.

FIRST... we need a script to construct the clip from images:

---begin "image seq reader.avs"------------------------------------------------------------
LoadPlugin("C:\Program Files\megui\tools\ffms\ffms2.dll")

fc = 23808
base_filename = "D:\img\album1\img"
img_type = "png"
digits = 6
h = 2048
w = 2048
fpsrate = 1.00
w_filename = "width.txt"
h_filename = "height.txt"
newline = Chr(13) + Chr(10)
w_header = "Type int" + newline + "Default -1" + newline
h_header = "Type int" + newline + "Default -1" + newline
matte = BlankClip(length=fc,w,h,"RGB32",fpsrate,audio_rate=0,channels=0) #init globally
frame = BlankClip(length=0,w,h,"RGB32",fpsrate,audio_rate=0,channels=0) #init globally

#Build returnclip
rclip = ScriptClip(matte,"""
cf = current_frame
img_filename=base_filename+RightStr("000000000"+String(cf),digits)+"."+img_type
frame=ImageSource(file=img_filename, start=0, end=0, fps=fpsrate, use_DevIL=false, info=false, pixel_type="RGB32")
return Layer(matte, frame, "add", level=257)
""")

rclip = WriteFileStart(rclip, w_filename, "w_header", append=true)
rclip = WriteFileStart(rclip, h_filename, "h_header", append=true)
rclip = WriteFile(rclip, w_filename, "String(current_frame) + Chr(32) + String(frame.Width())")
rclip = WriteFile(rclip, h_filename, "String(current_frame) + Chr(32) + String(frame.Height())")

return rclip.ConvertToYV12()

---end "image seq reader.avs"------------------------------------------------------------


...And to extract the images:


---begin "image seq writer.avs"------------------------------------------------------------

#LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\GScript.dll")
LoadPlugin("C:\Program Files\megui\tools\ffms\ffms2.dll")

srce_filename = "D:\img\album1.mp4"
dest_filename = "D:\img\extract\img" #includes image filename prefix
dest_delimiter = "_"
image_type = "png"
w_filename = "width.txt"
h_filename = "height.txt"

FFVideoSource(srce_filename)

w = FFVideoSource(srce_filename).Width()
h = FFVideoSource(srce_filename).Height()
fc = FrameCount()
i = 0 #iteration

ScriptClip("""
cf = current_frame
ImageWriter(Trim(cf, -1).ConvertToRGB().Crop(0,0,img_w,img_h), dest_filename+RightStr("000000"+String(cf),6)+dest_delimiter, 0, 0, image_type, info=false)
AddBorders(0,0, w-img_w, h-img_h, $111111)
ConvertToYV12()
""")

ConditionalReader(h_filename, "img_h", show=false)
ConditionalReader(w_filename, "img_w", show=false)

---end "image seq writer.avs"------------------------------------------------------------

MANY avisynth shortcomings quickly became apparent when I got into this project. Although it's not common for video to have varying frame dimensions, here it is a necessity. I found I couldn't even TEMPORARILY have a frame a different size, it had to be another clip entirely. There also appears to be no way to attach metadata to a clip or a specific frame, hence the parallel data files "width.txt" and "height.txt"

Constructing those files was no picnic either, due to the basic flaw of having separate per-script commands and per-frame commands, and variable scope issues. To make matters worse, basic control structure and conditional operators (for-next and if-then-else) loops are not possible in the normal fashion without an add-on such as Gscript. Gscript actually worked great, but didn't return a single frame until the entire clip was constructed. Basic file handing is also missing.

If that wasn't enough, I learned that avisynth has a bad habit of ignoring commands which do not contribute to the final output, requiring hacks.

DEVELOPMENT SUGGESTIONS:
Avisynth could *greatly* benefit from an additional mode that allows more straightforward scripting, the use of current_frame referencing globally, if-then statements, for-next loops, and an option to elminate the ignoring of commands which don't affect the final output, some sort of "force" option.

New object types: More than anything else, what's missing are frame and metadata classes. ( http://avisynth.org/mediawiki/Script_variables ). A clip object would consist of a set of frames, and both frame and clip classes would contain metadata classes, which users could extend, depending on the desired destination container.

A "force" option which guarantees all commands would execute (unless restricted by conditional control structure, of course, i.e. "IF(i>2)AND(i<1)THEN" would never happen)

Output: Some sort of console and video output would be great. MessageClip() and similar functions are useful, but a poor substitute.

The existing WriteFile() and ConditionalReader() functions are dependent on clip objects. Basic "normal" file I/O functionality would be highly useful, and scriptwriters could customize and extend their configuration files to their heart's content. I'd suggest FileOpen(), FileClose(), FileWrite(), FileRead(), each returning a bool for error condition, which could be read by GetFileError(). The important thing is these commands would be completely independent of clip or frame objects.

Finally, extending ImageSource() and ImageWriter() to be methods of a frame class would be a lifesaver. I see this has been somewhat solved by others' excellent work with the Immaavs and Corona plugins, although it appears Immaavs does not handle subfolders with wildcards, and I don't believe the Corona plugin can't return the filename into a string, it can only write it to the image.

This takes me to my next battle and where I could use some help: What's a good way to pick up where the Corona reader leaves off? Specifically, I'd like these scripts to handle an entire folder, including subfolders, and get the filenames into a string, so that they can be written to a file along with the dimensions, keep track of how many images are written, etc. The writing script would then recreate the path.

Lastly, I greatly appreciate the contributions of those that have taken avisynth as far as it has and who have posted about their problems and solutions, they've been a big help when found via Google searches. I understand avisynth's limitations are the result of the thinking at the time it was initially designed a decade or more ago, along with limitations of the AVI container itself (which led to problematic hacks such as the "packed" bitstream, a hack which caused far more problems than it solved).

Best regards,
turbine

jmac698
5th August 2012, 12:18
I agree with a lot of what you're saying, but a reply you will get may be, that Avisynth wasn't made for this kind of thing so you shouldn't use it. Someone might also say it's easier to do this in a plugin.

I like developing in script because of the immediacy of the write-test cycle. There's some workarounds for some of what you're saying, but I've been thinking of making some kind of array package to deal with the meta-frame issue.

I don't like having to add a bunch of plugins either, but with avslib, ffms2, grunt, gscript, you can get around a lot of limitations.

As for alternatives, imagemagick has a script, it's difficult too but fairly powerful.

If you want change, the best way is to write it yourself and try to get a patch accepted.

SEt
5th August 2012, 15:06
Avisynth scripts are not imperative programs "apply this to that", but rather more like functional programming – it describes filter connection path, but how actually frames flow, which frames are processed/skipped and in what order greatly depends on filters. Avisynth has no knowledge how to "process everything".

TheFluff
5th August 2012, 15:34
Avisynth script is pretty much babby's first graph description language. People seem to think that because it has conditionals and functions it's an actual general-purpose scripting language, but it isn't and it looks like you found that out the hard way.

In general, if you want to do something within the Avisynth framework that either doesn't seem doable or seems prohibitively complicated, the answer is almost always "do it with a different tool" or "do it in a plugin". You can do almost anything in plugins, especially if you only care about compatibility with yourself, because then you can basically treat video frames like arbitrary memory buffers and do whatever you want.

Asking for new features in Avisynth is not going to get you anywhere, really. The codebase is really showing its age and the framework has so many silly limitations that it's really not worth building on. Furthermore, there is only one active developer of note (IanB) who is even working on it at all, and his priorities run more to fixing bugs and cleaning up code than adding new features (the upcoming version, Avisynth 2.6, has been in development for several years and still doesn't really offer anything new or interesting at all, except a few new colorspaces).

turbine
5th August 2012, 18:33
Thanks for the replies. I would have probably learned a lot sooner had I been able to POST in the first five days.

SEt, that's exactly the point, It needs to be able to "process everything." Nobody writes a "just execute this if you feel like it" command.
TheFluff, sounds like AviSynth needs a rewrite from the ground up, or to be abandoned for a better video scripting language.

What's a better video scripting language to use instead? Ideally one that Avisynth could optionally call for compatibility purposes, with two lines like such as:

LoadPlugin("C:\Program Files\megui\tools\ffms\videoscript2012.dll")
VideoScript2012("Video Generated with a versatile object-oriented video scripting language.vs2")

StainlessS
5th August 2012, 20:08
It needs to be able to "process everything."

Dont be silly.

Goodbye.

jmac698
5th August 2012, 20:49
No, he has a point. Why would a language not execute certain commands? The answer lies in the type of optimizing Avisynth does. It tries hard to not run filters when it doesn't have to. It also has a cache system of processed frames. The most hasic example is SelectEvery. This will process only the frames requested.

The way around this is to ensure that all frames are requested.
Check out the call plugin which can call any other program from script.

Again, ImageMagick has it's own script language.

gyth
5th August 2012, 20:54
Nobody writes a "just execute this if you feel like it" command.
http://en.wikipedia.org/wiki/Lazy_evaluation

The opposite of lazy actions is eager evaluation, sometimes known as strict evaluation. Eager evaluation is commonly believed as the default behavior used in programming languages.[citation needed]

Can I use this thread as a citation? :devil:

What's a better video scripting language to use instead?
Add avisynth support to Python???

turbine
5th August 2012, 21:10
Thank you jmac, the point is obvious to most, I'd even call it a no-brainer. At a minimum it should have the ability to DISABLE the feature, or better documented workarounds. It's more than frames, of course -- not all statements are clip/frame related.

Stainless's dismissive attitude is not unique, it's one which has plagued software engineering for decades. The result is we often see software designed with limited regard for how others will use it because it's often designed by people with limited regard for others.

I'll check out ImageMagick. My first attempt with it didn't run, but I didn't troubleshoot it when I learned it wouldn't solve the subdirectory problem.

I appreciate the responses.

jmac698
5th August 2012, 21:20
I sort of agree with you; Avisynth may be "not meant" to do the things I want to do, but there's simply no other choice I've found. I did actually go as far as to try to do something in ImageMagick, and I wrote a script in it. But there's still a lot of useful filters in Avisynth/Virtualdub that I can't get elsewhere. There's another option though; calling Avisynth from say, a .net program and combing the two, but if you could program at that level, you probably wouldn't need much help.

Something else that comes close is Matlab. It's an interactive script, you can write a GUI in it, it imports video, and there's "toolboxes" for it. There's free clones like freemat, octave, etc.

turbine
5th August 2012, 21:38
I was thinking C++, not C# or other .NET platform, more cross-platform that way. Java is another option.

"Lazy Evaluation" -- appropriately named. Should be OFF by default, I'd argue, but most would settle for the ability to turn it off. It sounds like many of the common problems people have posted about for years could have been avoided by having this ability combined with a better solution for runtime commands, but that starts to get back into the topic of redesigning it from the ground up.

I too didn't see much choice, megui depends on avisynth. I may just see about wrapping the whole thing in a C++ or C# app. Thanks again.

StainlessS
5th August 2012, 21:52
I appreciate the responses.

You're Welcome. :devil:

Sorry for the being dismissive. It's really horses for courses and Avisynth is unlikely to change as desired.
As Jmac suggests, ImageMagick might be the better choice.

I also empathize with the 5 day post gripe, they could at least tell you before you register and save you the bother.

Welcome to the site, and have a nice day whether you stay or not. :)

SEt
5th August 2012, 22:08
You people just don't understand what Avisynth script is. Again: it is not a program. It's a path, graph. The script is not executed, so there is nowhere to apply strict or lazy evaluation.

gyth
5th August 2012, 22:49
At a minimum it should have the ability to DISABLE the feature, or better documented workarounds.
I might not be understanding the problem you are having.
I think I've run into similar issues with imagewriter.

http://avisynth.org/mediawiki/ImageWriter
Note that frames are not written to the output file until they are actually rendered by ImageWriter. Therefore, output is produced only for rendered frames, and there will be no output at all if the result of the filter does not contribute to the final result of the script.
a=ImageSource("sm444.png")

a.subtitle("not rendered").ImageWriter("not_rendered", type="png")

a.subtitle("rendered").ImageWriter("rendered", type="png")

Is your issue something like that?

TheFluff
5th August 2012, 22:56
No, he has a point. Why would a language not execute certain commands? The answer lies in the type of optimizing Avisynth does. It tries hard to not run filters when it doesn't have to. It also has a cache system of processed frames. The most hasic example is SelectEvery. This will process only the frames requested.

I think you've misunderstood how it works. As several people have pointed out, Avisynth script isn't an imperative programming language, it's a dataflow-oriented graph description language. As SEt says, the script isn't really executed; it just describes a graph through which the environment pulls video frames, where some nodes happen to have side-effects.

As for "everything should be possible", there is a reason why we don't have One Programming Language To Rule Them All. One size does not fit all, and while Avisynth script isn't very sophisticated and lacks some potentially useful features, it does make it very easy to create video filter chains, which is what it was intended for. If you really do want everything to be possible, program in assembly language (or better yet, machine code), and if that sounds too complicated for you, maybe you should sacrifice some possibilities for the convenience of simplicity.

turbine
5th August 2012, 23:49
I understand Avisynth is not a typical scripting language, and doesn't behave like a programming language. I'm just sayin' it SHOULD, or at least would be highly beneficial if it WOULD. I don't expect it to, it sounds like it's almost as dead as Latin, and probably the next place for the community to go would be an object-oriented successor, which will probably happen at some point by a whole new set of individuals to solve a different problem. Open-source and other similar projects are funny like that.

Interesting comparison, I used to code 8-bit assembly in my teens and early 20's back in the 80's and 90's. I can't see that sort of approach being too popular in 2012-2015. :)

StainlessS
6th August 2012, 02:26
Output: Some sort of console and video output would be great. MessageClip() and similar functions are useful, but a poor substitute.

In appeasement for my being dismissive, thought I might submit something that may partially fulfill your above requirement,
I was going to implement this anyway, just not planning to do it today, here an extract from the RT_Stats thread in
Avisynth usage forum (about to place an update there with the below update):


RT_debug(string s1, ... , string sn)
Non-clip function. Takes one or more strings, joins them together and then outputs the combined
string to OutputDebugString(), if strings are NOT space separated, it inserts a single space between them.
Useful during development Compile-time/Run-time scripts to monitor status in real time.
Use DebugView utility to view and capture output.
http://technet.microsoft.com/en-gb/sysinternals/bb545027

Usage eg:- RT_debug("TestFunc:", "["+String(current_frame)+"]","Going pretty good so far @","Line "+String(19))

In DebugView, filter for eg "TestFunc:" to skip all the extraneous stuff generated by other plugins/programs.
(In DebugView "Menu:Edit-Filter/Highlight", and enter "TestFunc:".


EDIT: Here:
http://forum.doom9.org/showthread.php?t=165479

TheFluff
6th August 2012, 08:16
I don't really understand what you want to accomplish with your script, but it doesn't look very complicated and I don't understand why you've chosen Avisynth as your tool even after determining beyond a shadow of doubt that it isn't very suitable for the task. I think you'd have a lot better luck with hacking something together using Perl and ImageMagick.

I understand Avisynth is not a typical scripting language, and doesn't behave like a programming language. I'm just sayin' it SHOULD, or at least would be highly beneficial if it WOULD. I don't expect it to, it sounds like it's almost as dead as Latin, and probably the next place for the community to go would be an object-oriented successor, which will probably happen at some point by a whole new set of individuals to solve a different problem. Open-source and other similar projects are funny like that.

If you want a real programming language, use a real programming language. Language design is very hard and it's much easier to create bindings for an existing language than it is to invent a new one. Unfortunately, Avisynth's collection of filters are pretty tightly tied to the scripting language, so it's really hard to create useful bindings for a different language.

I don't really understand your hardon for object-orientedness either. The class/object/inheritance model is a poor way to represent video frames and video clips, and most filter cores are written in very low-level C (or even assembler) for performance reasons. The choice of C++ for the Avisynth plugin interface has also proven to be a very bad choice.

jmac698
6th August 2012, 10:07
>I think you've misunderstood how it works.
I was trying to translate points of view here. I understand his point of view and yours.

When you're new to Avisynth, all these questions come up. I didn't find the manual very clear (in fact it still frustrates me, there's no real index to all keywords).

And saying it's a filter graph is just semantics; I can write a loop that does nothing but calculate a factorial, if I want to. You could even argue that it's Turiing complete and therefore like any other language. There's even GUI plugins to Avisynth; you can get keyboard input and interact with it just like a real program. Just let the video play forever and forget that it's a video, cause it's really a program ;)

turbine
6th August 2012, 10:15
Reasonable questions...

I chose Avisynth because I thought it was just a matter of getting the syntax set up right to get desired behavior, I didn't really think there was an alternative, and also to learn avisynth.

The goal is to be able to compress any given image library using x264, and extract it.

Object-oriented has been the standard for a long time due to its advantages. On the contrary it's the intuitive way to way to represent video and audio, the standard "is a" and "has a" questions we ask ourselves when creating classes. A video "has a" set of frames. A frame "has" one or more images (1080p vs. 480p, 1.77 AR vs. 1.33 for example), an image "has a" set of pixels.

Performance would take a hit, but isn't really a big concern when the weak link in the chain is typically the codec (x264 usually) and it's not realtime. Realtime frame-serving would arguably be a different story.

I realized it could be useful to create a parallel clip to store metadata, a RGB32 pixel can store a 32bit float or four ASCII characters, for example.

Problem is, I don't see a function to read/write individual pixels, only ShowPixelValues() which doesn't look like it returns the values. It doesn't appear PixelInfo() PsetRGB() is available anymore. http://forum.doom9.org/archive/index.php/t-108602.html.

Uncompressed audio could work if it's possible to read/write individual samples...I've not looked into it yet, though. I downloaded AVSLib, so I'll see what's possible between that and Gscript.

If Avisynth development is pretty much dead, then it is, and not much can be done about these concerns, which I gather are pretty common. On the other hand, if it is still commonly used, there's probably still value in adding a new run mode so that a user could choose to have it execute all commands as written, instead of it's current "lazy" execution model. Doesn't it seem like that would solve so many common problems?

jmac698
6th August 2012, 10:28
Like I said, you can use the call plugin to run a batch script or whatever, but it's only run once before the script starts.

Here's how to read and plot pixels:

Function GetPixel(clip clip, int x, int y) {
#Return luma of a pixel
current_frame=0
clip
IsYUY2 ? ConvertToYV12 : clip#AverageLuma only works on planar. YV12 is planar.
pointresize(6,6,x,y,1,1)#Blow up the pixel at x,y by 6 times (minimum possible with resize)
int(AverageLuma)
}

Function PutPixel(clip clip, int x, int y, int luma) {
#Plot a pixel
clip
ClipIsYV12=IsYV12
ClipIsYV12 ? ConvertToYUY2 : last
pointresize(width*2, height)
u=128
v=128
pixel=blankclip(last, color_yuv=luma*65536+u*256+v, width=2, height=1)
layer(last, pixel, "add", 256, x*2, y)#Layer only works with YUY2
pointresize(width/2, height)
ClipIsYV12 ? ConvertToYV12 : last
}

I have to tell you, I'm using an undocumented trick here. You can read a pixel once at the start on a specific frame, by setting current_frame. This lets you use the runtime variables, like AverageLuma. Remove the "current_frame=" line to use it as a runtime function. With the runtime way; averageluma has to appear inside scriptclip or one of the others.

The array implementation in avslib is quite slow. I have the same thoughts of a meta-data per-frame with another clip; but it could be added at the bottom. The garbage in the last few lines can be be cropped out.

You can extend this to RGB with showred.converttoyv12 for example. You could also make a kind of array in a clip by plotting pixels and reading them.

My slicer and addcode plugins can also read and plot int's on a line of video.
http://forum.doom9.org/showthread.php?p=1582574#post1582574

for myself: keywords pset, plot, plot a pixel, plot(x,y), pset(x,y)

edit: thank you me! I swear, this is the 5th time I've searched for this post.

TheFluff
6th August 2012, 13:22
And saying it's a filter graph is just semantics; I can write a loop that does nothing but calculate a factorial, if I want to. You could even argue that it's Turiing complete and therefore like any other language. There's even GUI plugins to Avisynth; you can get keyboard input and interact with it just like a real program. Just let the video play forever and forget that it's a video, cause it's really a program ;)

The fact that the scripting language allows you to write external functions in a general purpose language that gives you arbitrary side-effects does not change the fact that the scripting language just describes a graph. The entire script has a return value, which is the end point of that graph.

Object-oriented has been the standard for a long time due to its advantages. On the contrary it's the intuitive way to way to represent video and audio, the standard "is a" and "has a" questions we ask ourselves when creating classes. A video "has a" set of frames. A frame "has" one or more images (1080p vs. 480p, 1.77 AR vs. 1.33 for example), an image "has a" set of pixels.
Object oriented programming focuses on the interaction between data structures, but video frame buffers don't exactly need to talk to each other. The data structures you describe are all very simple and there's nothing particularly object oriented about them.

I don't deny that object oriented programming is very useful in many scenarios, but pretty much none of its big features (inheritance, encapsulation, polymorphism, data abstraction) are of any particular use for video processing. Complain about Avisynth script all you want, but the dataflow/graph paradigm was definitely the correct choice for the kind of video clip manipulation Avisynth was intended for. As for writing actual video filtering functions, you pretty much have to do that in a low-level compiled and unmanaged language in order to get it fast enough, and when you're on that level you pretty much work with plain byte arrays, so there's really no point to object-orienting anything.

Doing individual pixel manipulations in an interpreted language/managed code environment isn't really very useful in practice because even on modern hardware it's REALLY SLOW for any resolution bigger than a postage stamp, and at the time when Avisynth was designed it was, of course, a completely ridiculous idea, so the scripting language really doesn't try to help you when it comes to that kind of stuff.

Performance would take a hit, but isn't really a big concern when the weak link in the chain is typically the codec (x264 usually) and it's not realtime. Realtime frame-serving would arguably be a different story.
looks like you've never used a real-world avisynth script to actually do anything productive (hint: the frameserver is almost always the biggest bottleneck by far)

I realized it could be useful to create a parallel clip to store metadata, a RGB32 pixel can store a 32bit float or four ASCII characters, for example.

The complete inability to store any sort of per-frame or even per-clip metadata is one of Avisynth's greatest weaknesses.

Uncompressed audio could work if it's possible to read/write individual samples...
It is, if you write a plugin. Start to see a pattern emerging here?

Spoiler: the pattern is "don't use a simplistic graph description language if what you really want is an unmanaged environment that lets you poke arbitrary byte addresses". If you want C, write C.

On the other hand, if it is still commonly used, there's probably still value in adding a new run mode so that a user could choose to have it execute all commands as written, instead of it's current "lazy" execution model. Doesn't it seem like that would solve so many common problems?

Okay, let me try to explain this one final time.
Avisynth scripts are not executed. The script is compiled, yes, but the result of the compilation is a chain of filter functions, not a program that is executed. Absolutely nothing happens with it until the host application (which loaded the script) requests a video frame. At that point, Avisynth pulls the frame through the function chain, and it's only at this point that things happen in "filter" functions that have side effects (i.e. ImageWriter). In other words, if you want to call a function on each frame of a clip, you need to make sure all frames of that clip are actually requested, either directly by the host application or indirectly via something in your script (careful with that though, you may or may not run into funny issues if frames are requested multiple times).

Your idea that the environment should execute scripts imperatively is, of course, completely ridiculous. Just try thinking it through for a while and you'll probably realize why it's completely wrong to try to process an entire video clip procedurally instead of via a per-frame callback-driven data flow (just think of what kind of memory footprint a source filter that returns an entire clip at once would have). Incidentally, your idea would require changing so much of Avisynth that it'd be easier to just rewrite the entire thing from scratch.

StainlessS
6th August 2012, 17:06
@TheFluff,
Excellent Tutorial :)

gyth
6th August 2012, 20:09
I don't really understand what you want to accomplish with your script
Tar (http://en.wikipedia.org/wiki/Tar_%28file_format%29) with built-in lossy compression???

StainlessS
6th August 2012, 21:12
Originally Posted by TheFluff View Post
I don't really understand what you want to accomplish with your script

Tar (http://en.wikipedia.org/wiki/Tar_%28file_format%29) with built-in lossy compression???

I think TheFluff was replying to Turbine, and you were referring to your post:


a=ImageSource("sm444.png")

a.subtitle("not rendered").ImageWriter("not_rendered", type="png")

a.subtitle("rendered").ImageWriter("rendered", type="png")


In the 1st ImageWriter line the result is thrown away (temp assigned to Last and then overwritten
by following line), so the result is never used (neither is the source of the result, ie 1st ImageWriter,
nor the source of that ie the 'not rendered' Subtitle) as it plays no part in the output.

a simple

a=a.subtitle("not rendered").ImageWriter("not_rendered", type="png")


would solve the problem but for the two different outputs required by your script, one with
"not_rendered" on it and the other with "rendered", assuming that you actually want two different
outputs with two different subtitles, then you would need to somehow use the result of the 1st
ImageWriter line in the second.
(The problem here is there is only one output, but you want
to have a clip with two different subtitles, and not one overwriting
the other nor one without and one with a subtitle.
[in the words of a famous movie script, 'There Can Be Only One'])

There are any number of ways this could be done, eg


a=ImageSource("sm444.png")

Tmp = a.subtitle("not rendered").ImageWriter("not_rendered", type="png")

dummy = Tmp.FrameCount()
dummy = dummy - dummy

a.subtitle("rendered").ImageWriter("rendered",start=0+dummy, type="png")


Not tested but should I think work. (There are probably better ways)

EDIT: The dummy arg forces the 1st Imagewrite chain to be processed
as the output is reliant on both subtitled paths through the
graph, the advantages are that it is a highly efficient way
of selecting what is and is not necessary due to various conditions,
but results in seemingly silly kludges to force 'side effects' to occur.
Avisynth could well do some things better, but is quite remarkable in what
is does and the filter graph model itself is in no need of change.

gyth
7th August 2012, 00:50
Tar with built-in lossy compression???
That was my guess as to what turbine was trying to do.

Not tested but should I think work. (There are probably better ways)
And these better ways should be collected and linked to a faq and ImageWriter.

This one works for me
a = ImageSource("sm444.png")

a0 = a.subtitle("not rendered").ImageWriter("not_rendered", type="png")

a1 = a.subtitle("rendered").ImageWriter("rendered", type="png")

stackhorizontal(a1, a0).crop(0, 0, a1.width, a1.height)

StainlessS
7th August 2012, 00:58
Perhaps a "Return me a zero", and "Return me a one" should be added to the clip status returns
so you dont have to be silly and be so creative.
Was hard to tell what comment you were replying to, sorry, got it wrong.
The '???' was a clue but I EVENTUALLY got it wrong just the same, Shoot me!

gyth
7th August 2012, 02:27
Maybe add a function designed to produce side effects easily. (while minimizing overhead)
function render_both_return_first(clip c1, clip c2) {
????
}

turbine
7th August 2012, 12:04
Thanks, for the replies, guys.... I have had my hands full with a big event, I'll have more time later today or tomorrow.

Fluff, As far as script execution goes you're arguing terminology -- I get it; it's event driven, the processing or "execution" of the various commands happens when a frame is requested.

jmac698
9th August 2012, 00:19
And here's how to "execute" an Avisynth script without showing any frames:
http://forum.doom9.org/showthread.php?t=165528

You could wrap this all up into a program that processes text files, and never know it had anything to do with video. Rename it "sh.exe" and no one would be the wiser!

TheFluff
9th August 2012, 00:32
And here's how to "execute" an Avisynth script without showing any frames:
http://forum.doom9.org/showthread.php?t=165528

You could wrap this all up into a program that processes text files, and never know it had anything to do with video. Rename it "sh.exe" and no one would be the wiser!

That still retrieves all frames, even if it just discards them immediately after retrieving them.

pbristow
14th August 2012, 17:53
Fluff, As far as script execution goes you're arguing terminology -- I get it; it's event driven, the processing or "execution" of the various commands happens when a frame is requested.

Turbine, no he isn't! He's pointing out fundamental design concepts that have to do with achieving the best possible video processing performance on barely adequate hardware. Many of us are doing complex, heavyweight processing that absolutely dwarfs the CPU time and memory allocation required by a mere codec, and in that context, Avisynth's *fundamental design concept* of only processing the frames that will actually make a difference to the output is absolutely the right one *in most cases*. In the rare cases that it causes a problem, there are various workarounds available.

Avisynth has some flaws, sure, but "not being a totally different animal" isn't one of them!

I'm going to have to agree with the overall concensus here and say, if you want a tool that works in a completey different way to AviSynth, then use a tool that isn't AviSynth. If the tool you want doesn't exist yet, then start recruiting a team to create one. (Hint: Annoying the people who might very well be glad to join such a team by denigrating the work they've already done on another project is probably not conducive to succesful recruitment!).

If you can figure out how to make the new tool compatible with Avisynth plug-ins, you (and your users) would get the benefit of all the work that's already been done over the last decade in creating a huge variety of awesomely powerful video processing tools. You could even give it an Avisynth-like syntax, if you think that would be helpful... But you would probably find that designing an appropriate syntax to suit the way your new tool works would be better.

Good luck! :)

Gavino
7th September 2012, 09:41
[Catching up on recent threads after a long absence]


a=ImageSource("sm444.png")

Tmp = a.subtitle("not rendered").ImageWriter("not_rendered", type="png")

dummy = Tmp.FrameCount()
dummy = dummy - dummy

a.subtitle("rendered").ImageWriter("rendered",start=0+dummy, type="png")


Not tested but should I think work. (There are probably better ways)

EDIT: The dummy arg forces the 1st Imagewrite chain to be processed
as the output is reliant on both subtitled paths through the
graph ...
That doesn't work, since Framecount is known at compile time and does not require run-time access to frame data.
You need something that forces rendering of the frames, such as gyth's example:
a = ImageSource("sm444.png")

a0 = a.subtitle("not rendered").ImageWriter("not_rendered", type="png")

a1 = a.subtitle("rendered").ImageWriter("rendered", type="png")

stackhorizontal(a1, a0).crop(0, 0, a1.width, a1.height)

StainlessS
7th September 2012, 19:45
Thank you Maestro,
glad you're back, think D9 was about to go into mourning. :)

Chikuzen
12th September 2012, 15:51
why don't you use ImmaAVS?
ImmaRead() has 'size_x' and 'size_y' options to resize/pad automatically to the size you specified.