View Full Version : ImageWriter usage problem


mroz
28th October 2007, 21:47
I want to use ImageWriter in a script where it isn't processing frames from the last clip & I'm neither interested in the clip it's given being passed back to last, therefore I can't insert it into the script via

ImageWriter(...)

where it acts on the last clip & returns said clip.

I didn't think this would be a problem as I expected to be able to do something like:

blankclip()
dummy=ImageWriter(version(), file="E:\", start=0, end=0, type="ebmp")
last

However while this doesn't produce an error, it doesn't give me any saved frames either.

Is this intended behaviour? Am I doing something wrong?

Edit:

This is odd. If I write

blankclip().subtitle("hi")
saved=last
ImageWriter(version(), file="E:\", start=0, end=0, type="ebmp")

I get my frames saved. However with

blankclip().subtitle("hi")
saved=last
ImageWriter(version(), file="E:\", start=0, end=0, type="ebmp")
saved

no frames are written to disk. It seems it won't work unless its return clip is somehow further used in the script. So, let's try...

blankclip().subtitle("hi")
saved=last
ImageWriter(version(), file="E:\", start=0, end=0, type="ebmp")
overlay(saved, last, opacity=0)

Yup. This effectively discards the result, via a very roundabout route, & we do still get our frames written to disk. While the following which blatantly ignores the clip returned by imagewriter

blankclip().subtitle("hi")
saved=last
ImageWriter(version(), file="E:\", start=0, end=0, type="ebmp")
overlay(saved, saved, opacity=0)

saves no frames.

Surely this can't be correct behaviour?

Edit: Side question - how do you get a single frame out of imagewriter, when the frame you want is the first? The syntax implies pass start=end=<frame number>=0, but the case end=0 is used explicitly to flag all frames to the final one.

mroz
28th October 2007, 22:35
This is the actual script I'm working on:

#SetMTMode(2,0)
root="E:\Work\test\"
ftype="jpg"
leaf1="noSetMT"
leaf2="SetMT-v2"
global c1=AVISource(root+"hfyu_MVMT-test-"+leaf1+".avi")
global c2=AVISource(root+"hfyu_MVMT-test-"+leaf2+".avi")
global total=0
global file="E:\Work\test\compare-"+leaf1+"-"+leaf2+".log"
BlankClip(c1, width=640, height=640) # maybe 15% faster than using c1 as our 'dummy' clip (& 100% faster than using subtract(c1,c2) with variation subtitled)
WriteFileStart(file, """ "vim:tabstop=6"+chr(10) """, """ Time("%#c")+chr(10) """, """ "Frame"+chr(9)+"Total"+chr(9)+"Variation" """, append=true)
WriteFileEnd(file, """ "Test complete."+chr(10) """)
ScriptClip( """
variation = LumaDifference(c1,c2)+ChromaUDifference(c1,c2)+ChromaVDifference(c1,c2)
# nb1 keeping writefile inside here allows us to store variation as local, reducing problems with running in MTMode 2
# nb2 aside: writefile doesn't want to when called inside FrameEvaluate; anyone know why?
# nb3 sometimes the running total is reported incorrectly in MTMode 2 as another thread updates the total before code writes out data to log;
# this isn't terribly important & can be corrected as is implicit in data set
# nb4 compare against 0.0001 instead of 0 to allow for rounding errors - 2 identical files will report a variation of 0.000022
WriteFileIf(file, "variation>0.000022", "current_frame", "chr(9)", "thistotal", "chr(9)", "variation")
global total = total + ((variation>0.000022) ? 1 : 0)
thistotal = total # massively reduce chance of MTMode 2 screwing up logging of total
dummy = (variation>0.000022 && total<10) ? Eval("
#SetMTMode(5)
clip = Overlay(last, ImageWriter(subtract(c1,c2).ConvertToRGB(), file=root, start=current_frame, end=current_frame, type=ftype), opacity=0)
#SetMTMode(2)
return clip
" ) : last
return dummy
""" )

now using the above horrible hack to kick ImageWriter into life. It works, but I don't like the hack.

More problematic, it won't work with SetMTMode, even with the call to ImageWriter made in mode 5 (before I added ImageWriter use it worked fine). Any way round this? The script isn't usable without SetMTMode, as speed is essential & the frames I'm exporting are few in number, so can always be generated after the fact using the log which the main script spits out.

Fizick
29th October 2007, 00:18
About first post:
It is correct behaviour.
Imagewriter won't work unless its return clip is somehow further used in the script.

May be try end=-1 ?

About second post: I do not understand why overlay.

foxyshadis
29th October 2007, 00:48
All you have to do is follow the call structure - when ImageWriter gets referenced, it saves. All of the times it never saves was because it was bypassed; avisynth doesn't even look at anything that isn't referenced. But the simplest way to save out an image that you never use anywhere in the script is exactly how you have it. You can push it into a function to make it cleaner if it looks too ugly for you.

No idea about setmtmode though. =\

IanB
29th October 2007, 08:01
As Fizick and Foxyshadis have said it has to be part of the GetFrame chain for it to write frames.

Overlay is a pretty heavy duty filter with a colour space conversion to and from it's internal YV24 for all clips.

The lowest overhead trick I can think of to do this would be StackVertical of 2 lines from the ImageWriter clip. i.e....
Tmp = subtract(c1,c2).ConvertToRGB()
Tmp = Tmp.ImageWriter(file=root, start=current_frame, end=current_frame, type=ftype)
Tmp = Tmp.Crop(0,0,0,2)
Tw = Width() - Tmp.Width()
Tmp = Tw > 0 ? Tmp.Addborders(0,0,Tw,0) : Tmp.Crop(0,0,Width(),0)
clip = StackVertical(last, Tmp).Crop(0, 0, 0, Height())
...Crop is a zero cost filter, AddBorders if required is a small memcopy and a small memfill. The stackvertical will be 1 full frame blit plus a 2 line blit.

A simple zero cost filter to do this would be very trivial. It would just need to do a GetFrame call on each input clip, return the 1st as a result and discard the rest. I have added it to my todo list.

foxyshadis
29th October 2007, 11:17
mt_merge(good,ignoreme,blankclip(good),chroma="copy first") for now then? I think with old masktools they didn't have to match at all, with this one they do, though. Still not zero cost, one of the other mt functions might be a tiny bit faster.

mroz
30th October 2007, 03:17
Thanks for the feedback all, most appreciated :)

Glad I'm not going more barmy than I thought.

@Fizick: so end=-n will give n frames? I'll try that when my current encodes have finished. I'm pretty sure that's not mentioned in the docs, if it does work that way. Otherwise it's an oversight in the call spec for the function.

I take it no one can help with SetMTMode? Shame, as that makes this whole query academic for me, though still a useful analysis to help my understanding of avisynth. Cheers guys.

Edit: I was slow to reply as I never received email notification of the replies, despite being subscribed with instant notification & receiving notifications successfully for other threads I'm subbed to. Odd.

Fizick
30th October 2007, 05:43
mroz,
no, end=-1 trick may not work like Trim(), but we may ask it for next Avisynth version :)

tsp
30th October 2007, 12:12
mroz: A solution could be to create 4 avs file that each take care of 1/4 the comparison and run them in 4 instances of virtualdub

mroz
30th October 2007, 13:21
@Fizick: Thanks, I'll take your word for that. Shame.

So can I just confirm that currently, ImageWriter provides no means to request saving of only the first frame in a clip?

@tsp: Thanks for the suggestion, but as the exported frames were only of secondary importance I'll probably use a second script to harvest bad frames, if I bother automating it now.

Maybe a bit of perl to read the log, construct an avs with a series of concatenated single frame trims & one imagewriter call - that'll get around the problem of frame 0 too. While it's at it, it might as well invoke both avs giving a single click solution. Knowing me I'll not bother though, unless I need to do anymore testing of mvtools I suppose.

Then again, if I was going to do that I might as well adopt your idea to break the task into four as well to avoid all the multithreading issues.