Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
8th February 2015, 03:22 | #1 | Link |
Semper Tiro
Join Date: Jan 2015
Location: Denmark
Posts: 29
|
MCTD and memory
I'm new to Avisynth, jumping in because I'm looking to do some noise reduction. I'm working with DSLR timelapse image sequences that I'm making a film from, importing the sequences in Adobe After Efffects for post processing (such as pan/zoom). For best results I should apply the noise reduction to the original image sequences where most of the image is static from frame to frame, and due to the further processing I generally can't reduce the resolution before denoising. Images are mostly 12MP, in some cases 21MP.
The only hardware I have available for the task is an ASUS G73JH laptop (i7-720QM, 8GB RAM, ATI Mobility Radeon HD 5870 w. 1 GB RAM). As you can guess, my initial attempts were not successful. Using Avisynth 2.5.8 because 2.6 made MCTD crash. Starting out very basic: Code:
Import("C:\Path\to\MCTemporalDenoise.v1.4.20.avsi") ImageSource("I:\Path\to\DSC_%05d.jpg", 0, 99, 23.976) ConverttoYv12() MCTemporalDenoise(settings="low") ConvertToRGB24() Questions: 1) Is it possible to do some memory management to prevent errors? SetMemoryMax() seems to make no difference. 2) How do I most effectively lower MCTD's memory consumption without crippling it too much? Last edited by flyvholm; 8th February 2015 at 03:27. |
8th February 2015, 03:45 | #3 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,010
|
Have you tried with "MCTemporalDenoise(settings="low")" commented out ?
Have you tried low setting for SetMemoryMax(), eg SetMemoryMax(256) ? Some of the functions in Avisynth do not cope with frame bigger than about 4Kx4K eg AverageLuma() (at least up to v2.6 Alpha 5). EDIT: @PDR, 12 -> 21 MP.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
8th February 2015, 06:15 | #4 | Link |
Semper Tiro
Join Date: Jan 2015
Location: Denmark
Posts: 29
|
The 12MP images are 4256x2832 pixels, 21MP are 5616x3744. Both resolutions open fine when MCTD is commented out. I did try SetMemoryMax(256), both with or without GPU, and it made no difference in either case.
Monitoring the task manager, VirtualDub "only" takes ~870MB of memory with a 12MP sequence opened. This is with > 50% memory free. When trying to open a 21MP sequence VirtualDub fails with an out-of-memory error when hitting 1GB (memory usage appears to be directly proportional to resolution btw). But from what I read, 32-bit Avisynth + VirtualDub should be able to use up to 2GB. So I wonder why I run short at < 1GB? With 12MP sequence open VirtualDub status bar shows: Avisynth read error: GetFrameBuffer: Returned a VFB with a 0 data pointer! size=91527424, max=268435456, used=294194112 I think we have run out of memory folks! |
8th February 2015, 07:36 | #5 | Link |
Anime addict
Join Date: Feb 2009
Location: Spain
Posts: 673
|
Try SetMemoryMax(1024)
__________________
Intel i7-6700K + Noctua NH-D15 + Z170A XPower G. Titanium + Kingston HyperX Savage DDR4 2x8GB + Radeon RX580 8GB DDR5 + ADATA SX8200 Pro 1 TB + Antec EDG750 80 Plus Gold Mod + Corsair 780T Graphite |
8th February 2015, 11:47 | #6 | Link | |
Join Date: Mar 2006
Location: Barcelona
Posts: 5,034
|
Quote:
Avisynth tries to allocate memory for the number of frames requested by the filter and throws the error if there is not enough available. The memory usage you read in Taskmanager shows the current state. One way to increase the available memory to Avisynth is to pipe the script to the client application (avs2yuv, etc). If the piping application is "Large Address Aware", up to 4 GB can be allocated on a 64 Bit OS. I have not used MCTD but maybe there are settings with less memory usage. Lastly - How about a non-temporal noise filter? Last edited by Groucho2004; 8th February 2015 at 12:45. |
|
8th February 2015, 18:22 | #7 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,010
|
Perhaps try temporal Hqdn3d() or FFT3DFilter() or Spatial Vaguedenoise().
EDIT: I'm not aware of any RGB temporal denoisers to avoid colorspace conversions, anybody suggestions ?
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 8th February 2015 at 19:59. |
9th February 2015, 02:27 | #8 | Link |
Retried Guesser
Join Date: Jun 2012
Posts: 1,371
|
What if you processed the frames in slices to lower peak memory requirements?
Say you split each into 9 smaller frames, processed them, then joined them together again? Sounds simple, but you need overlap between the slices for a smooth result. Here's some code for you to try (it seems to work OK in a quick test): Code:
Assert(IsClip(Last) && IsYV12(Last), \ "YV12 source required for noise filter") Assert(Last.Width>48 && Last.Height>48, \ "source resolution too low") pad=8 ## size of mirror border / overlapped area as rq'd pad2=2*pad wid=Width hgt=Height wid3 = Round(wid/3.0) hgt3 = Round(hgt/3.0) new_wid = wid3 - (wid3 % 2) new_hgt = hgt3 - (hgt3 % 2) ## create the 9 slices ## (slice numbers refer to position in 'numeric keypad' aka Subtitle notation) C7=Crop(0, 0, new_wid+pad, new_hgt+pad) \ .MirrorBorderLTRB(pad, pad, 0, 0) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C8=Crop(new_wid-pad, 0, new_wid+pad2, new_hgt+pad) \ .MirrorBorderLTRB(0, pad, 0, 0) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C9=Crop(2*new_wid-pad, 0, wid-2*new_wid+pad, new_hgt+pad) \ .MirrorBorderLTRB(0, pad, pad, 0) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C4=Crop(0, new_hgt-pad, new_wid+pad, new_hgt+pad2) \ .MirrorBorderLTRB(pad, 0, 0, 0) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C5=Crop(new_wid-pad, new_hgt-pad, new_wid+pad2, new_hgt+pad2) \ .MirrorBorderLTRB(0, 0, 0, 0) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C6=Crop(2*new_wid-pad, new_hgt-pad, wid-2*new_wid+pad, new_hgt+pad2) \ .MirrorBorderLTRB(0, 0, pad, 0) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C1=Crop(0, 2*new_hgt-pad, new_wid+pad, hgt-2*new_hgt+pad) \ .MirrorBorderLTRB(pad, 0, 0, pad) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C2=Crop(new_wid-pad, 2*new_hgt-pad, new_wid+pad2, hgt-2*new_hgt+pad) \ .MirrorBorderLTRB(0, 0, 0, pad) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) C3=Crop(2*new_wid-pad, 2*new_hgt-pad, wid-2*new_wid+pad, hgt-2*new_hgt+pad) \ .MirrorBorderLTRB(0, 0, pad, pad) \ .Crop(0, 0, new_wid+pad2, new_hgt+pad2) ## join the 9 slices temporally - add 30 frames of filler at each end: count=Last.FrameCount T = C7.Trim(0, 29).Reverse + C7 + C7.Trim(count-30, 0).Reverse \ + C8.Trim(0, 29).Reverse + C8 + C8.Trim(count-30, 0).Reverse \ + C9.Trim(0, 29).Reverse + C9 + C9.Trim(count-30, 0).Reverse \ + C4.Trim(0, 29).Reverse + C4 + C4.Trim(count-30, 0).Reverse \ + C5.Trim(0, 29).Reverse + C5 + C5.Trim(count-30, 0).Reverse \ + C6.Trim(0, 29).Reverse + C6 + C6.Trim(count-30, 0).Reverse \ + C1.Trim(0, 29).Reverse + C1 + C1.Trim(count-30, 0).Reverse \ + C2.Trim(0, 29).Reverse + C2 + C2.Trim(count-30, 0).Reverse \ + C3.Trim(0, 29).Reverse + C3 + C3.Trim(count-30, 0).Reverse #return T ## x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ## NOTE: if memory is still a problem, split the script at this point: ## create a lossless dub of the above video, then continue ## with the rest of this script using the dub. #T = AviSource("lossless.avi") ## do noise processing etc ## (I don't have MCTemporalDenoise handy, but here is where it would go) #T = T.hqdn3d(0, 0, 35, 25, 40) #T = T.TemporalSoften(3, 28, 36, 28, 2) ## extract the slices from the processed video: count2=framecount+60 P7=T.Trim(30, -framecount) P8=T.Trim(30+count2, -framecount) P9=T.Trim(30+2*count2, -framecount) P4=T.Trim(30+3*count2, -framecount) P5=T.Trim(30+4*count2, -framecount) P6=T.Trim(30+5*count2, -framecount) P1=T.Trim(30+6*count2, -framecount) P2=T.Trim(30+7*count2, -framecount) P3=T.Trim(30+8*count2, -framecount) ## crop off the padding P7=P7.Crop(pad, pad, new_wid, new_hgt) P8=P8.Crop(pad, pad, new_wid, new_hgt) P9=P9.Crop(pad, pad, wid-2*new_wid, new_hgt) P4=P4.Crop(pad, pad, new_wid, new_hgt) P5=P5.Crop(pad, pad, new_wid, new_hgt) P6=P6.Crop(pad, pad, wid-2*new_wid, new_hgt) P1=P1.Crop(pad, pad, new_wid, hgt-2*new_hgt) P2=P2.Crop(pad, pad, new_wid, hgt-2*new_hgt) P3=P3.Crop(pad, pad, wid-2*new_wid, hgt-2*new_hgt) ## reconstruct the frame from slices and exit: StackVertical( \ StackHorizontal(P7, P8, P9), \ StackHorizontal(P4, P5, P6), \ StackHorizontal(P1, P2, P3) \ ) return Last ################################## # function MirrorBorderLTRB(clip C, \ int "bdrLt", int "bdrTp", int "bdrRt", int "bdrBt") { bdrLt = Max(2, Default(bdrLt, 16)) bdrTp = Max(2, Default(bdrTp, 16)) bdrRt = Max(2, Default(bdrRt, 16)) bdrBt = Max(2, Default(bdrBt, 16)) bdrLt = Max(0, bdrLt - (bdrLt % 2)) bdrTp = Max(0, bdrTp - (bdrTp % 2)) bdrRt = Max(0, bdrRt - (bdrRt % 2)) bdrBt = Max(0, bdrBt - (bdrBt % 2)) CL = C.Crop(0, 0, bdrLt, 0) CR = C.Crop(C.Width-bdrRt, 0, bdrRt, 0) C2 = (bdrLt==0) \ ? (bdrRt==0) \ ? C \ : StackHorizontal(C, CR.FlipHorizontal) \ : (bdrRt==0) \ ? StackHorizontal(CL.FlipHorizontal, C) \ : StackHorizontal(CL.FlipHorizontal, C, CR.FlipHorizontal) CT = C2.Crop(0, 0, 0, bdrTp) CB = C2.Crop(0, C2.Height-bdrBt, 0, bdrBt) C3 = (bdrTp==0) \ ? (bdrBt==0) \ ? C2 \ : StackVertical(C2, CB.FlipVertical) \ : (bdrBt==0) \ ? StackVertical(CT.FlipVertical, C2) \ : StackVertical(CT.FlipVertical, C2, CB.FlipVertical) return C3 } __END__ Last edited by raffriff42; 9th February 2015 at 02:49. Reason: typo |
9th February 2015, 04:49 | #9 | Link |
Semper Tiro
Join Date: Jan 2015
Location: Denmark
Posts: 29
|
Thanks for all the input! I tried SetMemoryMax() with values from 256 to 2048. It doesn't appear to make any difference in memory consumption.
I also tried using avs2yuv to pipe to x264 (64-bit). I get the same Avisynth out-of-memory error when hitting ~1GB of memory usage. I've seen VirtualDub take up to about 1.5GB of memory for something else (that crashed too ), so I don't know why it seems impossible to allocate more than 1 GB for this task. I'm working with nighttime timelapse footage. It needs strong noise reduction and mostly works quite favorably with temporal filters, so I do want to take advantage of that. I tried FFT3DFilter() on its own. I suspect that's the big memory hog inside MCTD, and it crashes (access violation) if I use the MCTD "high" settings. I can open the 12MP image sequence with default settings, but once I try to encode VirtualDub just hangs. Hqdn3d() appears to be a whole different beast. Opens even 21MP image sequences fine and processing is fast! It looks like it will do the job in at least some cases, but I suspect it will fall short in others. We'll see, it's at least something to get me started. Also, I'm able to open 1080p footage with MCTD, so even though it's not ideal it's an option to use that on the finished video. @raffriff42: That is awesome. I was thinking of that, but being new to Avisynth it would have taken a lot of effort to get all of that figured out. Unsure of success, I wouldn't even have attempted. But what an excellent illustration of the power of knowing how to use scripting. With the rising popularity of 4K (and timelapse for that matter) I could see this come in handy for many others. I haven't tested yet, but I will do that and return with results (or questions ). |
9th February 2015, 05:13 | #10 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,010
|
Yeh nice work rr42 - ever the show off
If Hqdn3d() works ok, then there is another filter (that I have never actually tried) but is also very fast, and because it is very fast I suspect that it may too work ok (fast == less memory usage - Probably), FluxSmooth(). Might also be worth a try. EDIT: Fluxsmooth: http://avisynth.nl/index.php/FluxSmooth
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 9th February 2015 at 10:27. |
9th February 2015, 05:35 | #11 | Link | |
Registered User
Join Date: Dec 2002
Location: Region 0
Posts: 1,436
|
Quote:
The Noise Ninja Photoshop plug-in worked pretty well at removing noise from still photos when I played with it in several years ago. It was highly customizable. |
|
9th February 2015, 06:50 | #12 | Link | |
Semper Tiro
Join Date: Jan 2015
Location: Denmark
Posts: 29
|
Thanks for continued suggestions - I won't be running out of things to experiment with any time soon.
Quote:
EDIT: @Stereodude: I think I see... the title video we've been playing with looks like it's panning across a single image, but it's actually an image sequence (you can tell because the noise changes from frame to frame). Last edited by flyvholm; 9th February 2015 at 06:59. |
|
9th February 2015, 10:02 | #13 | Link | |
Join Date: Mar 2006
Location: Barcelona
Posts: 5,034
|
Quote:
|
|
10th February 2015, 11:27 | #14 | Link | |
Semper Tiro
Join Date: Jan 2015
Location: Denmark
Posts: 29
|
Quote:
avs2yuv "input.avs" -raw - | x264 --crf 20 --output "output.mkv" - 4256x2832 raw [error]: raw input requires a resolution. x264 [error]: could not open input file '-' error: wrote only 17399278 of 18079488 bytes AFAICT this syntax works for others. What am I missing? |
|
10th February 2015, 11:42 | #15 | Link | |
Join Date: Mar 2006
Location: Barcelona
Posts: 5,034
|
Quote:
Code:
avs2yuv "script.avs" -o - | x264 - --crf 20 --frames 1000 --output "output.mkv" --demuxer y4m Last edited by Groucho2004; 10th February 2015 at 11:47. |
|
14th February 2015, 03:41 | #17 | Link |
Semper Tiro
Join Date: Jan 2015
Location: Denmark
Posts: 29
|
The sample script in the first post (minus the RGB conversion) would fail. However, with the --demuxer option set instead of resolution (as suggested by Groucho2004) the process completed. So that is potentially one way to work around the memory issue.
Admittedly, this topic is of much less interest to me after I was pointed to Neat Video. Getting that as a plugin for After Effects means that I can easily integrate it in my project files (i.e. no need to render intermediate, denoised footage), I get live previews as I tweak settings and I avoid color space conversions. On top of that it seems to work extremely well. I think I'd be hard pressed to produce as good results with Avisynth plugins, so for me Neat Video was the perfect solution and well worth the price. But. I am really grateful for the help I received here, and in particular I think the script posted by raffriff42 is pretty cool, so I would like to make that work because it could come in handy for others. I did manage to open a 12MP image sequence in VirtualDub, but the slices were garbled. And now somehow MCTD can't find FFT3DFilter anymore. I'm off for the weekend, but will try to work out the kinks when I get back. :-) |
14th February 2015, 19:56 | #18 | Link | |
Retried Guesser
Join Date: Jun 2012
Posts: 1,371
|
Quote:
Try removing the Reverse calls; they require perfect frame accuracy when decoding in reverse, which some codecs have trouble doing. These calls are probably overkill anyway... Code:
<...> #T = C7.Trim(0, 29).Reverse + C7 + C7.Trim(count-30, 0).Reverse #\ + C8.Trim(0, 29).Reverse + C8 + C8.Trim(count-30, 0).Reverse #\ + C9.Trim(0, 29).Reverse + C9 + C9.Trim(count-30, 0).Reverse #\ + C4.Trim(0, 29).Reverse + C4 + C4.Trim(count-30, 0).Reverse #\ + C5.Trim(0, 29).Reverse + C5 + C5.Trim(count-30, 0).Reverse #\ + C6.Trim(0, 29).Reverse + C6 + C6.Trim(count-30, 0).Reverse #\ + C1.Trim(0, 29).Reverse + C1 + C1.Trim(count-30, 0).Reverse #\ + C2.Trim(0, 29).Reverse + C2 + C2.Trim(count-30, 0).Reverse #\ + C3.Trim(0, 29).Reverse + C3 + C3.Trim(count-30, 0).Reverse T = C7 + C8 + C9 + C4 + C5 + C6 + C1 + C2 + C3 <...> #count2=framecount+60 #P7=T.Trim(30, -framecount) #P8=T.Trim(30+count2, -framecount) #P9=T.Trim(30+2*count2, -framecount) # #P4=T.Trim(30+3*count2, -framecount) #P5=T.Trim(30+4*count2, -framecount) #P6=T.Trim(30+5*count2, -framecount) # #P1=T.Trim(30+6*count2, -framecount) #P2=T.Trim(30+7*count2, -framecount) #P3=T.Trim(30+8*count2, -framecount) # P7=T.Trim(0 -framecount) P8=T.Trim(framecount -framecount) P9=T.Trim(2*framecount, -framecount) P4=T.Trim(3*framecount, -framecount) P5=T.Trim(4*framecount, -framecount) P6=T.Trim(5*framecount, -framecount) P1=T.Trim(6*framecount, -framecount) P2=T.Trim(7*framecount, -framecount) P3=T.Trim(8*framecount, -framecount) Last edited by raffriff42; 15th February 2015 at 04:35. Reason: missing /code tag |
|
18th February 2015, 03:03 | #19 | Link |
Semper Tiro
Join Date: Jan 2015
Location: Denmark
Posts: 29
|
That did the trick. There were a few additional tweaks to do. MCTD requires mod-4, and the input must initially be padded to be mod-12 to create a 3x3 grid with equal mod-4 slices. Also, the MirrorBorderLTRB() function was always adding padding on all sides, which doesn't appear to be what you intended. With that fixed the output did not need additional cropping. Below is a modified script that gave me "correct" results. One caveat is that we had to remove the filler frames at the start and end to avoid garbled output, but for a temporal filter like MCTD they ought to be included. It wasn't a problem for the footage I tested on, but in other cases it probably would be.
Code:
Assert(IsClip(Last) && IsYV12(Last), \ "YV12 source required for noise filter") Assert(Last.Width>48 && Last.Height>48, \ "source resolution too low") #The clip will be split into 9 slices (3x3 grid). Slices will be joined temporally, #then fed to a filter for processing. In this case the filter is MCTD and requires #input to be mod-4. First task is then to add padding to the clip so it can be split #into 9 equal slices that are mod-4. mod = 4 FrmPadTp = 3*mod - (Height % (3*mod)) FrmPadRt = 3*mod - (Width % (3*mod)) MirrorBorderLTRB(0, FrmPadTp, FrmPadRt, 0) pad=8 ## size of mirror border / overlapped area as rq'd pad2=2*pad wid=Width hgt=Height wid3 = Round(wid/3.0) hgt3 = Round(hgt/3.0) new_wid = wid3 - (wid3 % mod) new_hgt = hgt3 - (hgt3 % mod) ## create the 9 slices ## (slice numbers refer to position in 'numeric keypad' aka Subtitle notation) C7=Crop(0, 0, new_wid+pad, new_hgt+pad) \ .MirrorBorderLTRB(pad, pad, 0, 0, mod) C8=Crop(new_wid-pad, 0, new_wid+pad2, new_hgt+pad) \ .MirrorBorderLTRB(0, pad, 0, 0, mod) C9=Crop(2*new_wid-pad, 0, wid-2*new_wid+pad, new_hgt+pad) \ .MirrorBorderLTRB(0, pad, pad, 0, mod) C4=Crop(0, new_hgt-pad, new_wid+pad, new_hgt+pad2) \ .MirrorBorderLTRB(pad, 0, 0, 0, mod) C5=Crop(new_wid-pad, new_hgt-pad, new_wid+pad2, new_hgt+pad2) \ .MirrorBorderLTRB(0, 0, 0, 0, mod) C6=Crop(2*new_wid-pad, new_hgt-pad, wid-2*new_wid+pad, new_hgt+pad2) \ .MirrorBorderLTRB(0, 0, pad, 0, mod) C1=Crop(0, 2*new_hgt-pad, new_wid+pad, hgt-2*new_hgt+pad) \ .MirrorBorderLTRB(pad, 0, 0, pad, mod) C2=Crop(new_wid-pad, 2*new_hgt-pad, new_wid+pad2, hgt-2*new_hgt+pad) \ .MirrorBorderLTRB(0, 0, 0, pad, mod) C3=Crop(2*new_wid-pad, 2*new_hgt-pad, wid-2*new_wid+pad, hgt-2*new_hgt+pad) \ .MirrorBorderLTRB(0, 0, pad, pad, mod) ## Join the 9 slices temporally. This may cause problems with filters ## that mix data from adjacent frames unless filler frames are added ## at start and end. T = C7 + C8 + C9 + C4 + C5 + C6 + C1 + C2 + C3 #return T ## x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ## NOTE: if memory is still a problem, split the script at this point: ## create a lossless dub of the above video, then continue ## with the rest of this script using the dub. #T = AviSource("lossless.avi") ## do noise processing etc T = T.MCTemporalDenoise(settings="medium") ## extract the slices from the processed video: P7=T.Trim(0, -framecount) P8=T.Trim(framecount, -framecount) P9=T.Trim(2*framecount, -framecount) P4=T.Trim(3*framecount, -framecount) P5=T.Trim(4*framecount, -framecount) P6=T.Trim(5*framecount, -framecount) P1=T.Trim(6*framecount, -framecount) P2=T.Trim(7*framecount, -framecount) P3=T.Trim(8*framecount, -framecount) ## crop off the padding P7=P7.Crop(pad, pad, new_wid, new_hgt) P8=P8.Crop(pad, pad, new_wid, new_hgt) P9=P9.Crop(pad, pad, wid-2*new_wid, new_hgt) P4=P4.Crop(pad, pad, new_wid, new_hgt) P5=P5.Crop(pad, pad, new_wid, new_hgt) P6=P6.Crop(pad, pad, wid-2*new_wid, new_hgt) P1=P1.Crop(pad, pad, new_wid, hgt-2*new_hgt) P2=P2.Crop(pad, pad, new_wid, hgt-2*new_hgt) P3=P3.Crop(pad, pad, wid-2*new_wid, hgt-2*new_hgt) ## reconstruct the frame from slices StackVertical( \ StackHorizontal(P7, P8, P9), \ StackHorizontal(P4, P5, P6), \ StackHorizontal(P1, P2, P3) \ ) #Finally, remove the padding that was added before making slices Crop(0, FrmPadTp, -FrmPadRt, 0) return Last ################################## # function MirrorBorderLTRB(clip C, \ int "bdrLt", int "bdrTp", int "bdrRt", int "bdrBt", int "mod") { Defined(mod) ? Eval(""" bdrLt = ((bdrLt % mod) > 0) ? bdrLt + mod - (bdrLt % mod) : bdrLt bdrTp = ((bdrTp % mod) > 0) ? bdrTp + mod - (bdrTp % mod) : bdrTp bdrRt = ((bdrRt % mod) > 0) ? bdrRt + mod - (bdrRt % mod) : bdrRt bdrBt = ((bdrBt % mod) > 0) ? bdrBt + mod - (bdrBt % mod) : bdrBt """) : NOP bdrLt > 0 ? Eval("""CL = C.Crop(0, 0, bdrLt, 0)""") : NOP bdrRt > 0 ? Eval("""CR = C.Crop(C.Width-bdrRt, 0, bdrRt, 0)""") : NOP C2 = (bdrLt==0) \ ? (bdrRt==0) \ ? C \ : StackHorizontal(C, CR.FlipHorizontal) \ : (bdrRt==0) \ ? StackHorizontal(CL.FlipHorizontal, C) \ : StackHorizontal(CL.FlipHorizontal, C, CR.FlipHorizontal) bdrTp > 0 ? Eval("""CT = C2.Crop(0, 0, 0, bdrTp)""") : NOP bdrBt > 0 ? Eval("""CB = C2.Crop(0, C2.Height-bdrBt, 0, bdrBt)""") : NOP C3 = (bdrTp==0) \ ? (bdrBt==0) \ ? C2 \ : StackVertical(C2, CB.FlipVertical) \ : (bdrBt==0) \ ? StackVertical(CT.FlipVertical, C2) \ : StackVertical(CT.FlipVertical, C2, CB.FlipVertical) return C3 } __END__ |
Tags |
avisynth, mctd, memory management |
Thread Tools | Search this Thread |
Display Modes | |
|
|