Log in

View Full Version : InpaintFunc.avs - Different result depending on Avisynth version


Pages : [1] 2

hello_hello
2nd June 2015, 04:52
Has anybody noticed, and/or knows the reason why, InpaintFunc seems to work better when using Avisynth+, as opposed to Avisynth 2.6? At least in DeBlend mode. I'm not sure about the other modes yet.

I'm using Avisynth 2.6 RC3 at the moment but I'm pretty sure when I was using 2.6 RC1 it was exactly the same. Here's three screenshots to demonstrate the difference. All I'm doing is switching the Avisynth version MeGUI uses. The script is exactly the same, with the exception of not loading the ImageSeq plugin for Avisynth 2.6 as it's a built-in function.

#LoadPlugin("C:\Program Files\MeGUI\tools\avs\plugins\ImageSeq.dll")
LoadPlugin("C:\Program Files\MeGUI\tools\ffms\ffms2.dll")
FFVideoSource("E:\test.mkv", cachefile="D:\test.ffindex", fpsnum=25, fpsden=1, threads=1)
InpaintFunc(mask="D:\test.bmp", loc="86,4,-482,-276", mode="Deblend", speed=20, ppmode=3, pp=75)

No Logo removal
http://s14.postimg.org/4jsmcxrwx/image.jpg

InpaintFunc & Avisynth 2.6
http://s21.postimg.org/qzqmbyirb/image.jpg

InpaintFunc & Avisynth+
http://s13.postimg.org/m316cg1yf/image.jpg

Groucho2004
2nd June 2015, 09:04
Post a sample clip so we can reproduce this.

StainlessS
2nd June 2015, 10:31
Perhaps Avisynth+ has had some mod to work around this problem

Levels Bug ?

I assume, but could be wrong that the original Levels code used a min/max
limiting of the output, which at some later date was converted to using
PixelClip(), this in my opinion is a BUG, and certainly does not lay easy
with the original programmers intent.

I quote from the manual entry on the levels filter:-

"However, the input and output parameters can be larger than 255."

It seems to have been omitted that they could be less than zero too.

It is my assumption from the quote (that I take, to be from the original
Levels programmer), that the intent was to have no limits on either the
input nor output arguments to the levels filter, this was and is, quite a
sensible and flexible stance to take. Unfortunately, using PixelClip() has
almost completely negated the intent. As it now stands, PixelClip has a
slightly larger array (both +ve and -ve) than the normal 0-255 range to
presumably cope with slightly out of range results. BUT, as the quote above
points out, in levels, they could be deliberately far outside of the 0-255
range, much further than PixelClip was designed to 'contain'. PixelClip is
presumably designed to cope with eg rounding errors. In Levels, Arguments
outside the 0-255 range are not errors, only the eventual result should be
limited to the 0-255 range by a a simple min/max solution.

I say, put back what was I presume the original min/max limiting.

Unfortunately, there is at least one script that will fail badly if
the Levels code is amended, InPaintFunc.avs by Reuf Toc, for AVSInpaint.dll,
relies on the above problem. Reuf Toc, uses as output args 0-900,
and relies on PixelClip() out of PixelClip array, to produce all zero's
for those out of array elements. As it happens, it works quite well
as there seem to be a lot of zeros following the pixel clip array in
current versions of Avisynth, but only due to code link order.
I have a ripped out version of Levels source, only difference being that
it always outputs the LUT tables as text files (for use in comparing
Levels output with my Levels Grapher thing), and this alternate version of
the exact same code produces completely different results.

I say that PixelClip() in Levels is a BUG, put back min/max.

Perhaps I am wrong.

What Say YOU.

EDIT: the 0-900 thing in InPaintFunc.avs only affects the
postprocessing of edge of the logo.

Perhaps related, I dont know (InPaintFunc post processing should not really work properley at all now).

EDIT: The suggested mod to use min/max instead of PixelClip was adopted in Avisynth v2.6, perhaps AVS+ did something different.
EDIT: Maybe AVS+ even put back PixelClip, not realizing that it is a bug.

EDIT: Where the bug reliant code lives in InPaintFunc (about the script middle)

# crop of the part of the image where is the logo + mask creation
# ================================================================


cropped = clp.crop(a,b,c,d)
in = (RGB32 == true) ? cropped : cropped.converttoRGB24()
in2 = (spd == true) ? in.SelectRangeEvery (every=20, length=speed) : in

Masque = imagesource(mask,start=0,end=1).converttoRGB32
Masque = Masque.crop(a,b,c,d).levels(127,1,128,0,255)
Masque = Masque.mask(Masque)

BlendedMask = Masque.DirtyBlur().levels(0,1,75,0,255)
BlendedMask = BlendedMask.mask(BlendedMask)
RepairMask = BlendedMask.levels(0,1,255,0,pp)
RepairEdge = Masque.DirtyBlur().levels(0,1,255,0,900)
RepairEdge = RepairEdge.DirtyBlur().levels(0,1,75,0,pp)

StainlessS
2nd June 2015, 12:38
Here a test script [EDIT: RGB Levels Input on left half, output on right half frame]

RESULT=0

GSCript("""
for(n=0,255) {
current_frame = n # Pretend we are in runtime, ie make AverageLuma work EDIT: should be 0 but dont matter
color = (n * 256 + n) * 256 + n
C=BlankClip(Length=1,Color=color,width=320)
CR=C.Levels(0,1.0,255,0,900)
CRV = CR.ShowGreen(pixel_type="YV12").AverageLuma
CR=CR.SUBTITLE(String(CRV,"%.1f"),align=5)
C=C.SUBTITLE(String(n),align=5)
C=StackHorizontal(C,CR)
RESULT = (RESULT.IsClip) ? RESULT + C : C
}
""")

RESULT


Should saturate to 255 at input 73 and stay saturated.
Pixelclip bugged Levels will flip from white(255) to black(0) at input = 164 under eg v2.58

Does AVS+ produce identical output to AVS 26 ?

EDIT:
InPaintFunc requires something that produces same as bugged Levels(0,1.0,255,0,900) for RGB post processing,
eg set all input range 164 and above to 0 before call to Levels(0,1.0,255,0,900) [mt lut stuff Planar only, what else would work ?].

Wilbert
2nd June 2015, 12:56
I don't understand your post (#3). Are you saying that levels(0,1,255,0,900) gives different results for AviSynth and AviSynth+?

I also don't understand your comments about PixelClip versus min/max which IanB later changed (in 2011). See http://forum.doom9.org/showthread.php?t=159652&highlight=PixelClip
PixelClip was only applied for RGB clips and only on the end result (not on the input parameters). I see that IanB corrected it to use min/max (in 2011), but i don't see why it should have made a difference except for the end values larger than the upperbound 255+320.

edit: did "Array out of bounds territory." mean that it would return 0?

edit2: AviSynth+ uses the same code as far as i can see:


map[i] = clamp(int(p+0.5), 0, 255); // and 16,235) when coring=true

template<typename T>
T clamp(T n, T min, T max)
{
n = n > max ? max : n;
return n < min ? min : n;
}

StainlessS
2nd June 2015, 13:08
Wilbert,see the test script in post 4, try on both v2.58 and v2.6 to see difference.
edit: did "Array out of bounds territory." mean that it would return 0?

Yes, also see the edit.

Are you saying that levels(0,1,255,0,900) gives different results for AviSynth and AviSynth+?
Dont know, I was asking that of Hello Hello.

I'll install AVS+ and see.
Will post an edit here in a few moments.

StainlessS
2nd June 2015, 13:14
Just tested, AVS+ produces non bugged results, ie same as Avisynth v2.6 standard, so above PixelClip bug is nothing to do with the OP problem :(
(But InPaintFunc could still do with a resolution to correct the PixelClip fixed problem).

hello_hello
2nd June 2015, 14:52
Wow, thanks guys, especially StainlessS. You've overwhelmed me a bit. I'll have to re-read the posts and regroup. I might need to get back with some more info as required tomorrow, but for the moment I can at least confirm that levels(0,1,255,0,900) produces the same result using both Avisynth 2.6 and Avisynth+.

I'm working on a sample at the moment. I'll try to upload it tonight but it's getting late, so if it takes too much messing about...... tomorrow.

Thanks.

StainlessS
2nd June 2015, 15:11
Here a fix for v2.6 (and AVS+ v2.6) to make the InPaintFunc.avs mask work as in v2.58 prior to Levels bug fix.
Not related to the OP problem but there is a problem with the current InPaintFunc script in v2.6, perhaps only where different post processing mode.

Fix, replace Levels(0,1.0,255,0,900) with call to IPF_Mask() [req mask tools]

Function IPF_Mask(clip c) {
c.ShowGreen(pixel_type="YV12").Mt_Lut(Mt_Polish("(x >= 164) ? 0 : x"))
Return MergeRGB(Last,Last,Last).Levels(0,1.0,255,0,900)
}

RESULT=0

GSCript("""
for(n=0,255) {
current_frame = n # Pretend we are in runtime, ie make AverageLuma work EDIT: should be 0 but dont matter
color = (n * 256 + n) * 256 + n
C=BlankClip(Length=1,Color=color,width=320)
# CR=C.Levels(0,1.0,255,0,900)
CR=C.IPF_Mask()
CRV = CR.ShowGreen(pixel_type="YV12").AverageLuma
CR=CR.SUBTITLE(String(CRV,"%.1f"),align=5)
C=C.SUBTITLE(String(n),align=5)
C=StackHorizontal(C,CR)
RESULT = (RESULT.IsClip) ? RESULT + C : C
}
""")

RESULT


Above shows the same erroneous (but InPaintFunc required) behaviour as in eg v2.58 Levels using PixelClip.

EDIT: IPF_Mask returns RGB32 as supplied to Levels by Masque.DirtyBlur in original script

RepairEdge = Masque.DirtyBlur().levels(0,1,255,0,900)

hello_hello
2nd June 2015, 15:33
Okay..... a sample turned out to be pretty easy to come up with. It's part of an old AVI from a TV capture.

First, how it looks using my PC. The top pic is MeGUI displaying the script whilst using the portable version of Avisynth+ that comes with it, the bottom pic is MPC-HC displaying the same script via the "installed" Avisynth 2.6.0.6

http://s9.postimg.org/l6mmsbmjj/plus_vs_2_6.jpg

Edit: I Added an image of the original video without logo removal.

http://s24.postimg.org/il8gvjdut/original.jpg

To help check I'm not using some odd version of InpaintFunc or AVSInpaint I've included all the relevant files in the zip file below.

AVSInpaint.avsi is just the script I have in the Avisynth plugins folder to "autoload" AVSInpaint.dll
There's around 40 seconds of the video from an AVI that I split off and remuxed as MKV with the bitmap I'm using for logo removal and the script for encoding etc.
I'll be interested to learn if this is a "my PC" problem or if it's typical. I'm using XP if it matters.

Cheers.

InpaintFunc sample files.zip (http://ge.tt/7VDbFaH2/v/0)
(I kept it fun-size. It's only about 4MB)

hello_hello
2nd June 2015, 15:48
I'll return tomorrow to re-read your posts StainlessS. It's pretty late here, I'm tired and it's close to being over my head anyway, so I'll return when my brain's working.

Cheers.

Groucho2004
2nd June 2015, 16:03
Okay..... a sample turned out to be pretty easy to come up with. It's part of an old AVI from a TV capture.

First, how it looks using my PC. The top pic is MeGUI displaying the script whilst using the portable version of Avisynth+ that comes with it, the bottom pic is MPC-HC displaying the same script via the "installed" Avisynth 2.6.0.6
You must be using AVS+ r1576 which gives me the same result as in your top pic.
AVS+ r1825 and AVS 2.6 official show the problem as in your second pic.

Edit: All official Avisynth versions down to 2.5.7 seem to have the problem.

hello_hello
2nd June 2015, 16:13
The Avisynth+ dll in MeGUI's folder shows version 2.6.0.5 via the right click properties menu.

It seems you're right though...... there's only one Avisynth+ update file inside MeGUI's updates folder and it's labelled avisynthplus-r1576.7z, and Avisynth 2.6.0.5 can be found within.

StainlessS
2nd June 2015, 16:56
Hello, Hello_Hello

Tested with v2.58 (will not load ImageSeq under v2.58 so comment out)

The v2.6 standard result looks pretty much the same as in v2.58, kinda just what I expected as the AVS+ frames look weird to me
for InPaintFunc output, dont know what its doing but AVS+ is the odd one and not v2.6 standard (despite AVS+ looking perhaps better).

EDIT: Did not see Groucho's edit.

Groucho2004
2nd June 2015, 17:10
AVS+ is the odd one and not v2.6 standard (despite AVS+ looking perhaps better).
To be more specific: AVS+ r1576 and r1689 show the behaviour as in pic 1. All versions after these and all official AVS versions look like pic 2.

StainlessS
2nd June 2015, 17:51
Hello, Hello_Hello

Suggest you touch up your mask, the crud revealed in v2.6 standard is due to the mask not completely covering the logo
as can be seen when Show=true (shimmering logo will not be removed, need to cover halos, compression artifacts etc around logo) ie

InpaintFunc(mask="D:\_HELLO_HELLO\test.bmp", loc="84,4,-480,-276", mode="Deblend", speed=20, ppmode=3, pp=75,Reset=True,Show=True)


Use Reset=True so as to redo the logo detection and mask re-creation otherwise you may be viewing earlier results.
There is another problem in the script which I gave a fix for but was never incorporated and that is something to do
with re-saving the masks (otherwise sometimes not written out to file).
Here is the fix post:- http://forum.doom9.org/showthread.php?p=1443309#post1443309

Here both the fixes combined

# crop of the part of the image where is the logo + mask creation
# ================================================================


cropped = clp.crop(a,b,c,d)
in = (RGB32 == true) ? cropped : cropped.converttoRGB24()
in2 = (spd == true) ? in.SelectRangeEvery (every=20, length=speed) : in

Masque = imagesource(mask,start=0,end=1).converttoRGB32
Masque = Masque.crop(a,b,c,d).levels(127,1,128,0,255)
Masque = Masque.mask(Masque)

BlendedMask = Masque.DirtyBlur().levels(0,1,75,0,255)
BlendedMask = BlendedMask.mask(BlendedMask)
RepairMask = BlendedMask.levels(0,1,255,0,pp)
#RepairEdge = Masque.DirtyBlur().levels(0,1,255,0,900) # ssS fix (removed)
RepairEdge = Masque.DirtyBlur().IPF_Mask() # ssS fix (added)
RepairEdge = RepairEdge.DirtyBlur().levels(0,1,75,0,pp)


# check for an existing computed mask. If it doesn't exist or if reset = true --> computation
# ===========================================================================================


ID = mask + "InpaintFunc" + string(a) + string(b) + string(c) + string(d) + string(speed)

Logo = (reset == true) ? eval("""

in2.analyzelogo(Masque).trim(0,-1).converttoRGB32
imagewriter(ID,0,1,"ebmp")

""") : eval("""

try
{imagesource(ID + "%06d.ebmp",0,0)}
catch (dummy) {
show=true # ssS fix (added)
in2.analyzelogo(Masque).trim(0,-1).converttoRGB32
imagewriter(ID,0,1,"ebmp")
}""")


and append to end of script

Function IPF_Mask(clip c) { # ssS fix (added), Correction for fixed Levels bug. Returns RGB32
c.ShowGreen(pixel_type="YV12").Mt_Lut(Mt_Polish("(x >= 164) ? 0 : x"))
Return MergeRGB(Last,Last,Last).Levels(0,1.0,255,0,900)
}


EDIT: Mask fix requires mask tools v2.
EDIT: You can remove the Reset=True arg when Show=True fix is added to InPaintFunc script.
With Show=True fix, if bmp is bad/not existent will auto show the masks (forcing bmp to be written), just close this
and re-open, 2nd time will use the newly written bmp. (A better solution than Show=True would use v2.6 Echo somewhere).
By the way, I think the script makes global changes to clip (not just logo area) might want to chop out area of interest and
process just that and omit two colorspace conversions to boot (for most of the frame).

EDIT: posted by Wilbert
i don't see why it should have made a difference except for the end values larger than the upperbound 255+320.
The IPF_Mask thing, fixes levels output 255+320 before it happens with Mt_Lut(Mt_Polish("(x >= 164) ? 0 : x"),
after levels it would be too late to do anything, Levels(0,1.0,255,0,900) with input 164 must result in 255+320 (have not checked this),
I got the 164 from the bugged behaviour of the posted GScript script under v2.58 (where levels uses PixelClip rather than min/max).
End result is that IPF_Mask() produces the same as v2.58 Levels using PixelClip which InPaintFunc relies upon to produce 'hollowed out' edge masks.
I think that it does not matter at all in the posted Hello_Hello example, but only because the mask is too thin to 'hollow out', it is also too thin
(needs dilation) to produce a good de-logo'd result.

hello_hello
3rd June 2015, 10:46
Firstly,
StainlessS.... you mentioned touching up the mask, but I'm not sure what to touch up. What I'm seeing when I open the mask bitmap in Irfanview and increase it to around 8x it's original size is this:

http://s22.postimg.org/437g82wy9/bitmap_enlarged.jpg

Which looks nothing like the mask when show=true is being used:

http://s2.postimg.org/jfr7wds2h/mask.jpg

Given the mask is a bitmap, could it be some sort of subsampling or resizing issue when it's converted?
Although no...... it looks the same when MeGUI is using Avisynth+ and show=true is included in the script.

When using show=true should the top right picture be an accurate representation of the end result?
Because when using Avisynth 2.6, frame number 386 looks like this:
http://s23.postimg.org/42lg1jtiz/mask2.jpg

But the actual script output is this:
http://s7.postimg.org/m5emfx2e3/output.jpg

StainlessS,
All of the above was after applying your suggested changes to the script but I gather they weren't expected to fix the problem. I thought I'd mention it though.

I did wonder if Avisynth+ 2.6.0.5 being the "odd one out", the output from the other Avisynth versions would be what's "expected" while the Avisynth+ output is not, even though it tends to remove more logo.

Having not used InpaintFunc until recently, but only with Avisynth+, I'd assumed it's output was normal until I noticed the difference. Could someone tell me.......
Avisynth+ and Avisynth 2.6 tend to be opposite ends of the scale to some extend. Avisynth+ removes the logo completely but the surrounding area (in this case a rough square slightly larger than the logo) tends to look "processed". Mostly you need to view the video in motion to see it, but it varies from almost impossible to detect to being not much better than typical "ugly blob" logo removal.
On the other hand there's generally not the same "processed block" when using Avisynth 2.6, but at the same time it doesn't remove all of the logo.
Which of those would be considered more "typical" in DeBlend mode?

That's been the extent of my further experimenting to date. I haven't discovered anything at all, although maybe provided some useful information?..... but whether the Avisynth 2.6 output should be considered correct or if it's the Avisynth+ output that's right, is it likely we'll ever discover why they're different?

Cheers.

hello_hello
3rd June 2015, 11:15
I tried again with a new mask. Something "overdone" compared to what I previously assumed would be needed. The Avisynth result did improve and only the ghost of logos past remained, but it's obvious due to the visible processed "square" area when using Avisynth+ that somehow, in some way, it must mean there's more/different processing going on when Avisynth+ 2.6.0.5 is used. I wonder why?

http://s14.postimg.org/4orgo3mo1/bitmapnew.jpg

Avisynth 2.6.0.6
http://s18.postimg.org/cyad3mhdl/2point6.jpg

Avisynth+ 2.6.0.5
http://s7.postimg.org/5qqpqr13v/plus.jpg


Now.... how to achieve an output that's a compromise between those two..... :)

Oh.... I did notice a little difference between the behaviour of the original script and the StainlessS modded version.
When opening a script with the "original" InpaintFunc included and no ebmp file has been created, there's a waiting period and the script eventually opens outputting the de-logoed video. The StainlessS version opens as though show=true was included in the script and to see the de-logoed output it needs to be previewed a second time.

Was that intentional StainlessS?

Thanks!

StainlessS
3rd June 2015, 12:41
Mobile currently.
Yes intentional and mentioned in edit.
I think the avs+ result is due to it eg not using the mask during post process repair (or something like that, is may be doing temporal soften on whole rectangular area, this might be fault in overlay with mask or similar in avs +)

Edit: the mask in top middle will show shimmering where the mask is too thin, due to eg compression artefacts that are bigger than the logo but affected by it.

hello_hello
3rd June 2015, 14:33
Mobile currently.
Yes intentional and mentioned in edit.

Sorry I missed that.
Is it safe to change "show" to false here? I did so without any apparent side effects so far.

try
{imagesource(ID + "%06d.ebmp",0,0)}
catch (dummy) {
show=false # ssS fix (added)
in2.analyzelogo(Masque).trim(0,-1).converttoRGB32
imagewriter(ID,0,1,"ebmp")
}""")

I'm trying to save a bit of time without confusing MeGUI in the process, so I've been creating the scripts and loading them into MeGUI's job queue with the InpaintFunc part commented out and no ebmp file created. That way I don't have to wait for the analyses while trying to load each one, then when they're all in the job queue I uncomment InpaintFunc in each script.

I initially thought I'd end up with a bunch of "show=true" encodes but for reasons I don't understand that doesn't happen, however somewhere along the way MeGUI still sees the resolution of the script with show=true active and thinks it needs to compensate for a change in resolution by getting all anamorphic..... or something like that..... and the upshot of it is the encoded version comes out looking something like this:

http://s16.postimg.org/4zwvjqr0l/aspect.jpg

With show=false it's business as usual.

I think the avs+ result is due to it eg not using the mask during post process repair (or something like that, is may be doing temporal soften on whole rectangular area, this might be fault in overlay with mask or similar in avs +)

I'll switch to Avisth 2.6 now and go with the assumption that's how the world is supposed to work and adjust the masks I create to suit. It definitely looks better without the "processed block"

Thanks for all the help everyone. I've got a better idea as to what's going on now.

PS StainlessS,
Could I get you to assume I'm Avisynth stupid and elaborate on what you meant by the following. Being Avisynth stupid I'm not sure I understand what you meant. Do you mean to somehow do this when encoding and removing the logo?
Thanks.

"By the way, I think the script makes global changes to clip (not just logo area) might want to chop out area of interest and
process just that and omit two colorspace conversions to boot (for most of the frame)."

StainlessS
3rd June 2015, 14:58
Still mobile.
See s_exlogo thread for a walk hrough.
Maybe don't need use s_exlogo though,your choice.

StainlessS
27th April 2016, 22:31
@Hello_Hello,

Sorry, I seem to have missed this post (#20) and was about to delete stuff related to it.

PS StainlessS,
Could I get you to assume I'm Avisynth stupid and elaborate on what you meant by the following. Being Avisynth stupid I'm not sure I understand what you meant. Do you mean to somehow do this when encoding and removing the logo?
Thanks.

"By the way, I think the script makes global changes to clip (not just logo area) might want to chop out area of interest and
process just that and omit two colorspace conversions to boot (for most of the frame)."


I meant that the filter alters the entire clip (converting to RGB and back again), so I would preferably crop out an area around
the logo, fix that, and then put it back, (Crop, Overlay or preferably StackH/V). In this manner, only the logo area suffers
two colorspace conversions (I'm not sure how much of the frame is affected by Overlay, hopefully no unnecessary conversions
if already YUV).

StainlessS
2nd January 2017, 16:40
Fixed InPaintFunc bug in RepairEdge Mask. (result of a bug fix in avs v2.6 Levels, produced bug in InPaintFunc)

Below Repair Edge mask now works as intended (did look exactly same as Repair Mask)
https://s20.postimg.cc/94tpsg6t9/fixed2_zpskkcgbohy.jpg (https://postimg.cc/image/oqb1ceird/)

InpaintFunc.avs Part 1 of 2.

#____________________________________________________________________________________
# _____ _ _ ______
# |_ _| (_) | | | ____|
# | | _ __ _ __ __ _ _ _ __ | |_| |__ _ _ _ __ ___
# | | | '_ \| '_ \ / _` | | '_ \| __| __| | | | '_ \ / __|
# _| |_| | | | |_) | (_| | | | | | |_| | | |_| | | | | (__
# |_____|_| |_| .__/ \__,_|_|_| |_|\__|_| \__,_|_| |_|\___|
# | |
# |_|
#_____________________________________________________________________________________



# InpaintFunc is a new delogo function using AVSInpaint.dll an AviSynth C plugin developed by AMSS.
#See thread : http://forum.doom9.org/showthread.php?t=133682 to download this plugin and get
#more information about it. Just an advertise : AVSInpaint plugin is rather slow so be patient ;-)


#_______________________________________________________________________________________
#
# History :
#_______________________________________________________________________________________


# Actual revision : InpaintFunc v1.12

# Author : Reuf Toc

# Requirement : AVSInpaint.dll


# Changes :

#Rev 1.00 : First release 2008/01/30
#Rev 1.01 : Added debug for "mode". Removed two useless operations.
#Rev 1.02 : Added "Speed" parameter.
#Rev 1.03 : Fixed bug in PAR calculation. Fixed bug with non-RGB32 mask.
#Rev 1.10 : Fixed bug due to overlay. Added post-processing + a lot of things.
#Rev 1.11 : Added Show parameter and InpaintAssist function. Process in RGB24 instead of RGB32.
#Rev 1.12 : Fixed bug in "loc" calculation
#Rev 1.13 : Fixed bug for .ebmp creation (did not happen in several cases)
#Rev 1.14 : Fixed RepairEdge bug resulting from a bug fix in Levels for RGB (http://forum.doom9.org/showthread.php?t=159652) [StainlessS).

#______________________________________________________________________________________
#
# About Inpainting :
#______________________________________________________________________________________


# Image Inpainting is the art of restoring destroyed parts of an image by using information
#of valid parts of the image in a way, so that the human eye does not recognize the damaged
#areas (at least not at a first sight). In video processing image inpainting is often applied
#to videos in order to remove TV station logos.


#______________________________________________________________________________________
#
# Function parameters :
#______________________________________________________________________________________




# =======================================================
# InpaintAssist
# =======================================================


# This subfunction can be used to help you in order to set your own crop values to isolate the logo to remove. With HD footage, the delogo
# process is slow due to the resolution (especialy for analysis) and to maximize speed, it is adviced to reduce the size of the cropped clip
# by setting your own crop values.


# If you don't specify a loc value, this function will display your clip divised in 9 parts (the nine loc preset of InpaintFunc) with the crop values for each one in order
# to give you an idea about the values to use.

# After that step, you can enter your own loc values and check they are correct. The selected area will be hightlighted.
# Keep in mind you have to keep a little border around the logo since inpainting use nearby pixels to compute the hidden ones.

# string "loc" : Select the part of the picture where is the logo to remove. Same as InpaintFunc loc parameter

# String "alignment" : Alignment of the text. "Top", "Center" and "Bottom" are allowed



# =======================================================
# InpaintFunc
# =======================================================



# Given this function use AVSInpaint.dll and given AVSInpaint is an avisynth C plugin
#don't forget to add loadCplugin("xxx\AVSInpaint.dll") in your script before calling this function !!!




# String "loc" : Select the part of the picture where is the logo to remove.
# See the table :


# ______________ ______________
# | TL | TC |TR | | X1 | X2 |X3 |
# |____|____|___| |____|____|___|
# | ML | MC |MR | or | Y1 | Y2 |Y3 |
# |____|____|___| |____|____|___|
# | BL | BC |BR | | Z1 | Z2 |Z3 |
# |____|____|___| |____|____|___|


# If the logo you want to remove is in the top right corner, then you can choose
# either loc="TR" or loc="x3".

# If you don't want to use one of these preset, you can enter manually the crop values to isolate the logo.
# example : loc = "0,300,-440,-20". Spaces are not allowed in "loc" parameter. You can use function
# InpaintAssist to help you to set crop values.




# String "mask" : Path to the mask of the logo. The mask is a black and white picture. Parties where the logo
# is are white, the others are black.

# example : mask="C:\my_mask.bmp"



# String "mode" : 3 Choices (default both) :

# -Deblend : If the logo is transparent, use this mode.
# -Inpaint : If the logo is opaque, use this mode.
# -Both : If the logo is both opaque and transparent, use this mode.



# Float "AR" : The Sample Aspect Ratio of your video. E.g. : 16/9, 4/3... (Default 1.0).
# This value is used to calculate the PAR of your video. If you don't set this parameter, then
# PAR will be set to 1:1. It's not really important if you don't set this value.
# When you set the AR, take care to add ".0" to your values if you use exact value (16/9 or 4/3).
# example : AR=16.0/9.0 or AR=4.0/3.0



# Int "Speed" : With this parameter you can speed up this function by trimming the clip analyzed by
# AnalyseLogo. A value of 20 means that 100% of clip will be analyzed. With a value of
# 1, only 5% will be analyzed. (min value 1, max value 20, default 5)


# Int "PPMode" : If you want to apply post-processing, 3 modes are available. Default is 0 (disabled)
# -Mode 1 : Blur all the area where logo was present.
# -Mode 2 : Blur all the area where logo was present using TemporalSoften and SpatialSoften.
# -Mode 3 : Blur only the edge of logo area using TemporalSoften and SpatialSoften..


# Int "PP" : Strength of the post-processing. Default is 50 (min value 0, max value 100)
# A 0 value will disable post processing, 100 will process at full strength.

# Bool "Reset" : InpaintFunc contain a feature that allow to not compute logo analysis when it was already done.
# By setting Reset to true, logo analysis is always computed. Default is false.

# Float "radius" : Radius around a damaged pixel from where values are taken when the pixel is inpainted.
# Bigger values prevent inpainting in the wrong direction, but also create more blur.

# Float "sharpness" : Higher values can prevent blurring caused by high Radius values.

# Float "preblur" : Standard deviation of the blur which is applied to the image before the structure tensor is computed.
# Higher values help connecting isophotes which have been cut by the inpainting region, but also
# increase CPU usage. PreBlur=0.0 disables pre-blurring.


# Float "postblur" : Standard deviation of the blur which is applied to the structure tensors before they are used
# to determine the inpainting direction. Higher values help gather more directional information when
# there are only few valid pixels available, but increases CPU usage.


# Bool "show" : Allow the user to see the differents steps of the delogoing. Are displayed the source, the
# repaired, the repaired post-processed, the mask, the repair masks (edge and global), the color
# mask, the alpha mask and the inpaint mask.




#______________________________________________________________________________________

# Function :
#______________________________________________________________________________________


function InpaintFunc( clip clp, string "mask", string "loc", float "AR", string "mode", int "speed",
\ int "pp", int "ppmode", bool "reset", float "radius", float "sharpness", float "preblur",
\ float"postblur", bool "show")

{

mask = default (mask , "" )
loc = default (loc , "" )
AR = default (AR , 1.0 )
mode = default (mode , "both")
speed = default (speed , 5 )
pp = default (pp , 50 )
ppmode = default (ppmode , 0 )
reset = default (reset , false )
radius = default (radius , 8.0 )
sharpness = default (sharpness , 75.0 )
preblur = default (preblur , 8.0 )
postblur = default (postblur , 4.0 )
show = default (show , false )




# debug
# =====


x = width (clp)
y = height (clp)
pp = (pp >= 100) ? 255 : (pp <= 0) ? 0 : int(pp*255/100)
RGB = isRGB(clp)
RGB24 = isRGB24(clp)
RGB32 = isRGB32(clp)
YUY2 = isYUY2(clp)
cropval = (StrLen(loc) != 2 ) ? true : false
spd = (speed != 20 ) ? true : false
PAR = (AR != 1.0) ? float( y) / float( x) * AR : 1.0
bugloc = (loc == "" ) ? true : false
bugmode = (mode != "inpaint" && mode != "deblend" && mode != "both") ? true : false
bugspeed = (speed <= 0 || speed >= 21) ? true : false


assert ( findstr(loc," ") == 0 , """Space character is not allowed in string "loc"."""")
assert ( mask != "" , """You have to define a mask (string "mymask")""")
assert ( bugloc == false , """You must define "Loc".""")
assert ( bugmode == false , """This mode doesn't exist. Change "mode" value.""")
assert ( bugspeed == false , """"Speed" value must be between 1 and 20.""")



# calculation of crop values
# ==========================


null = (cropval == false ) ? eval("""

a = (Rightstr(loc,1) == "L" || Rightstr(loc,1) == "1") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? round((x*1/6))*2 : round((x*1/3))*2
b = (leftstr(loc,1) == "T" || leftstr(loc,1) == "X") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? round((y*1/6))*2 : round((y*1/3))*2
c = (Rightstr(loc,1) == "R" || Rightstr(loc,1) == "3") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? -round((x*1/6))*2 : -round((x*1/3))*2
d = (leftstr(loc,1) == "B" || leftstr(loc,1) == "Z") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? -round((y*1/6))*2 : -round((y*1/3))*2

""") : eval("""

long = StrLen(loc)

posvirg1 = findstr(loc, ",")
posvirg2 = findstr(rightstr(loc,long-posvirg1), ",")
posvirg2 = posvirg2+posvirg1
posvirg3 = findstr(rightstr(loc,long-posvirg2), ",")
posvirg3 = posvirg3 + posvirg2

a = int(value(leftstr(loc,posvirg1-1)))
b = int(value(leftstr(rightstr(loc,long-posvirg1),posvirg2-posvirg1-1)))
c = int(value(leftstr(rightstr(loc,long-posvirg2),posvirg3-posvirg2-1)))
d = int(value(rightstr(loc,long-posvirg3)))
""")


# crop of the part of the image where is the logo + mask creation
# ================================================================


cropped = clp.crop(a,b,c,d)
in = (RGB32 == true) ? cropped : cropped.converttoRGB24()
in2 = (spd == true) ? in.SelectRangeEvery (every=20, length=speed) : in

Masque = imagesource(mask,start=0,end=1).converttoRGB32
Masque = Masque.crop(a,b,c,d).levels(127,1,128,0,255)
Masque = Masque.mask(Masque)

BlendedMask = Masque.DirtyBlur().levels(0,1,75,0,255)
BlendedMask = BlendedMask.mask(BlendedMask)
RepairMask = BlendedMask.levels(0,1,255,0,pp)
#RepairEdge = Masque.DirtyBlur().levels(0,1,255,0,900) # ssS fix (removed)
RepairEdge = Masque.DirtyBlur().IPF_Mask() # ssS fix (added)
RepairEdge = RepairEdge.DirtyBlur().levels(0,1,75,0,pp)


# check for an existing computed mask. If it doesn't exist or if reset = true --> computation
# ===========================================================================================


ID = mask + "InpaintFunc" + string(a) + string(b) + string(c) + string(d) + string(speed)

Logo = (reset == true) ? eval("""

in2.analyzelogo(Masque).trim(0,-1).converttoRGB32
imagewriter(ID,0,1,"ebmp")

""") : eval("""

try

{imagesource(ID + "%06d.ebmp",0,0)}
catch (dummy)

{in2.analyzelogo(Masque).trim(0,-1).converttoRGB32
imagewriter(ID,0,1,"ebmp") }""")


# Creation of the masks used for DeblendLogo and InpaintLogo
# ==========================================================


LogoColor = Logo.Crop(0,0,0,Logo.Height/2).converttoRGB24

LogoAlpha = Logo.Crop(0,Logo.Height/2,0,0)
Logoalpha = LogoAlpha.mask(LogoAlpha)

LogoInpaint = LogoAlpha.mask(masque.dirtyblur().levels(0,1,32,0,255))


# InpaintLogo and DeblendLogo are applied depending on the value of "mode"
# ==========================================================================


repaired = (mode == "both") ?
\ in.DeblendLogo(LogoColor,LogoAlpha).
\ InpaintLogo(LogoInpaint,radius=radius,sharpness=sharpness,preblur=preblur,postblur=postblur,PixelAspect=PAR).converttorgb32:
\ (mode == "deblend") ?
\ in.DeblendLogo(Logocolor,Logoalpha).converttorgb32 :
\ in.InpaintLogo(LogoInpaint,radius=radius,sharpness=sharpness,preblur=preblur,postblur=postblur,PixelAspect=PAR).converttorgb32


# Finalization of the repaired with post-processing
# ==========================================================


EDIT: 2 modded sections marked in Blue

StainlessS
2nd January 2017, 16:41
InpaintFunc.avs Part 2 of 2.



repairedpp = (ppmode == 1) ? repaired.layer(repaired.DirtyBlur( ).mask(RepairMask)) :
\ (ppmode == 2) ? repaired.layer(repaired.DirtyBlur(2).mask(RepairMask)) :
\ (ppmode == 3) ? repaired.layer(repaired.DirtyBlur(2).DirtyBlur().mask(RepairEdge)) : repaired


output = in.converttorgb32.Layer(repairedpp.Mask(BlendedMask))


# Overlay of the cleaned portion over the original clip
# =====================================================


(show == true) ? Eval("""

cropped = cropped.subtitle("source").converttoRGB32
masque = masque.subtitle("mask")

repairmask = repairmask.subtitle("repair mask")
repairedge = repairedge.subtitle("repair edge")

Logoalpha = Logoalpha.subtitle("Logo alpha")
Logocolor = Logocolor.subtitle("Logo color").converttoRGB32
Logoinpaint = Logoinpaint.subtitle("Logo inpaint")

repaired = repaired.subtitle("repaired")
repairedpp = repairedpp.subtitle("repaired pp")

l1 = Stackhorizontal(cropped,repaired,repairedpp)
l2 = Stackhorizontal(masque,repairmask,repairedge)
l3 = Stackhorizontal(logocolor,logoalpha,logoinpaint)

stackvertical (l1,l2,l3)
return spline36resize(last,width(last),height(last))

""") : Eval("""


clp = (RGB32 == true) ? clp : clp.converttoRGB32
fullclip = clp.layer(output,x=a, y=b)
fullclip = (RGB == true) ? (RGB32 == true) ? fullclip : fullclip.converttoRGB24() : (YUY2 == true) ? fullclip.converttoYUY2() : fullclip.converttoYV12()
return fullclip
""")

}


#==========================================================================================================
#==========================================================================================================
#==========================================================================================================


function InpaintAssist ( clip clp, string "loc", string "alignment") {


loc = default (loc, "")
x = width (clp)
y = height (clp)
alignment = default (alignment, "top")
align = (alignment == "top") ? 8 : (alignment == "center") ? 5 : (alignment == "bottom") ? 2 :8
framecount = framecount(clp)


# I "Loc" parameter is not specified, split the clip in 9 parts et show crop value for each part
# ==============================================================================================


loc == "" ? Eval("""

white = blankclip(width=round(x/3),height=round(y/3),color=$FFFFFF,length=framecount)
black = blankclip(width=round(x/3),height=round(y/3),color=$000000,length=framecount)

l1 = stackhorizontal(white,black,white)
l2 = stackhorizontal(black,white,black)
background = stackvertical(l1,l2,l1).converttoRGB32.spline36resize(x,y)
clp = clp.converttoRGB32

a1 = string(0)
a2 = string(round((x*1/6))*2)
a3 = string(round((x*1/3))*2)

b1 = string(0)
b2 = string(round((y*1/6))*2)
b3 = string(round((y*1/3))*2)

ca1 = string(-round((x*1/3))*2)
ca2 = string(-round((x*1/6))*2)
ca3 = string(0)

d1 = string(-round((y*1/3))*2)
d2 = string(-round((y*1/6))*2)
d3 = string(0)

c1 = clp.crop(0 , 0 , -round((x*1/3))*2, -round((y*1/3))*2)
\ .subtitle("TL (" + a1 + "," + b1 + "," + ca1 + "," + d1+ ")",align=8)
c2 = clp.crop(round((x*1/6))*2, 0 , -round((x*1/6))*2, -round((y*1/3))*2)
\ .subtitle("TC (" + a2 + "," + b1 + "," + ca2 + "," + d1+ ")",align=8)
c3 = clp.crop(round((x*1/3))*2, 0 , 0 , -round((y*1/3))*2)
\ .subtitle("TR (" + a3 + "," + b1 + "," + ca3 + "," + d1+ ")",align=8)

c4 = clp.crop(0 , round((y*1/6))*2 , -round((x*1/3))*2, -round((y*1/6))*2)
\ .subtitle("ML (" + a1 + "," + b2 + "," + ca1 + "," + d2+ ")",align=8)
c5 = clp.crop(round((x*1/6))*2, round((y*1/6))*2 , -round((x*1/6))*2, -round((y*1/6))*2)
\ .subtitle("MC (" + a2 + "," + b2 + "," + ca2 + "," + d2+ ")",align=8)
c6 = clp.crop(round((x*1/3))*2, round((y*1/6))*2 , 0 , -round((y*1/6))*2)
\ .subtitle("MR (" + a3 + "," + b2 + "," + ca3 + "," + d2+ ")",align=8)

c7 = clp.crop(0 , round((y*1/3))*2, -round((x*1/3))*2, 0)
\ .subtitle("BL (" + a1 + "," + b3 + "," + ca1 + "," + d3+ ")",align=8)
c8 = clp.crop(round((x*1/6))*2, round((y*1/3))*2, -round((x*1/6))*2, 0)
\ .subtitle("BC (" + a2 + "," + b3 + "," + ca2 + "," + d3+ ")",align=8)
c9 = clp.crop(round((x*1/3))*2, round((y*1/3))*2, 0 , 0)
\ .subtitle("BR (" + a3 + "," + b3 + "," + ca3 + "," + d3+ ")",align=8)

output = stackvertical(stackhorizontal(c1,c2,c3), stackhorizontal(c4,c5,c6), stackhorizontal(c7,c8,c9))
output = output.spline36resize(x,y)
clip1 = background.layer(output.mask(blankclip(output,color=$DEDEDE)))


""") : nop


# If "Loc" is specified, hightlight the part choosen by user
# ==========================================================


(strlen(loc) == 2) ? Eval("""

a = (Rightstr(loc,1) == "L" || Rightstr(loc,1) == "1") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? round((x*1/6))*2 : round((x*1/3))*2
b = (leftstr(loc,1) == "T" || leftstr(loc,1) == "X") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? round((y*1/6))*2 : round((y*1/3))*2
c = (Rightstr(loc,1) == "R" || Rightstr(loc,1) == "3") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? -round((x*1/6))*2 : -round((x*1/3))*2
d = (leftstr(loc,1) == "B" || leftstr(loc,1) == "Z") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? -round((y*1/6))*2 : -round((y*1/3))*2

""") : (strlen(loc) != 0) ? eval("""

long = StrLen(loc)
posvirg1 = findstr(loc, ",")
posvirg2 = findstr(rightstr(loc,long-posvirg1), ",")
posvirg2 = posvirg2+posvirg1
posvirg3 = findstr(rightstr(loc,long-posvirg2), ",")
posvirg3 = posvirg3 + posvirg2

a = int(value(leftstr(loc,posvirg1-1)))
b = int(value(leftstr(rightstr(loc,long-posvirg1),posvirg2-posvirg1-1)))
c = int(value(leftstr(rightstr(loc,long-posvirg2),posvirg3-posvirg2-1)))
d = int(value(rightstr(loc,long-posvirg3)))

""") : nop


(loc != "") ? eval("""

hightlight = blankclip(width=x-a+c,height=y-b+d,color=$96ff2d).converttoRGB32
clip2 = clp.converttoRGB32.layer(hightlight.Mask(blankclip(hightlight, color=$444444)),x=a,y=b)
return clip2.subtitle("Crop value : " + string(a) +", " +string(b) +", " +string(c) +", " +string(d), align=align, size=20 )

""") : clip1


return last
}


#==========================================================================================================
#==========================================================================================================
#==========================================================================================================



function dirtyblur(clip clp, int "mode") {
mode = default (mode, 1)

o = (mode == 1) ? clp.blur(1.58).GeneralConvolution (matrix="40 75 40 75 100 75 40 75 40").blur(1.58).blur(1.58).blur(1.58) :
\ clp.converttoYUY2.temporalsoften(1,64,64,mode=2,scenechange=6).spatialsoften(2,255,255).converttoRGB32

return o
}

Function IPF_Mask(clip c) { # ssS fix (added), Correction for fixed Levels bug. Returns RGB32
c.ShowGreen(pixel_type="YV12").Mt_Lut(Mt_Polish("(x >= 164) ? 0 : x"))
Return MergeRGB(Last,Last,Last).Levels(0,1.0,255,0,900)
}

EDIT: Single modded section Marked in Blue at end of script.

hello_hello
2nd January 2017, 19:13
Thanks for the update.

StainlessS
2nd January 2017, 19:21
Your Welcome HH, note, can also use in v2.58, (v2.58 does not suffer from the bug anyway).

StainlessS
2nd January 2017, 21:32
OK HH, here you go, (was actually quite simple).
Suggest you investigate using specific loc setting eg InPaintFunc("D:\Z\Test.BMP",loc="1580,0,0,-850") #Top RHS

InPaintFunc.avs v1.15, Part 1 of 2.

#____________________________________________________________________________________
# _____ _ _ ______
# |_ _| (_) | | | ____|
# | | _ __ _ __ __ _ _ _ __ | |_| |__ _ _ _ __ ___
# | | | '_ \| '_ \ / _` | | '_ \| __| __| | | | '_ \ / __|
# _| |_| | | | |_) | (_| | | | | | |_| | | |_| | | | | (__
# |_____|_| |_| .__/ \__,_|_|_| |_|\__|_| \__,_|_| |_|\___|
# | |
# |_|
#_____________________________________________________________________________________



# InpaintFunc is a new delogo function using AVSInpaint.dll an AviSynth C plugin developed by AMSS.
#See thread : http://forum.doom9.org/showthread.php?t=133682 to download this plugin and get
#more information about it. Just an advertise : AVSInpaint plugin is rather slow so be patient ;-)


#_______________________________________________________________________________________
#
# History :
#_______________________________________________________________________________________


# Actual revision : InpaintFunc v1.12

# Author : Reuf Toc

# Requirement : AVSInpaint.dll


# Changes :

#Rev 1.00 : First release 2008/01/30
#Rev 1.01 : Added debug for "mode". Removed two useless operations.
#Rev 1.02 : Added "Speed" parameter.
#Rev 1.03 : Fixed bug in PAR calculation. Fixed bug with non-RGB32 mask.
#Rev 1.10 : Fixed bug due to overlay. Added post-processing + a lot of things.
#Rev 1.11 : Added Show parameter and InpaintAssist function. Process in RGB24 instead of RGB32.
#Rev 1.12 : Fixed bug in "loc" calculation
#Rev 1.13 : Fixed bug for .ebmp creation (did not happen in several cases)
#Rev 1.14 : Fixed RepairEdge bug resulting from a bug fix in Levels for RGB (http://forum.doom9.org/showthread.php?t=159652) [StainlessS).
#Rev 1.15 : Affect loc area only [StainlessS).

#______________________________________________________________________________________
#
# About Inpainting :
#______________________________________________________________________________________


# Image Inpainting is the art of restoring destroyed parts of an image by using information
#of valid parts of the image in a way, so that the human eye does not recognize the damaged
#areas (at least not at a first sight). In video processing image inpainting is often applied
#to videos in order to remove TV station logos.


#______________________________________________________________________________________
#
# Function parameters :
#______________________________________________________________________________________




# =======================================================
# InpaintAssist
# =======================================================


# This subfunction can be used to help you in order to set your own crop values to isolate the logo to remove. With HD footage, the delogo
# process is slow due to the resolution (especialy for analysis) and to maximize speed, it is adviced to reduce the size of the cropped clip
# by setting your own crop values.


# If you don't specify a loc value, this function will display your clip divised in 9 parts (the nine loc preset of InpaintFunc) with the crop values for each one in order
# to give you an idea about the values to use.

# After that step, you can enter your own loc values and check they are correct. The selected area will be hightlighted.
# Keep in mind you have to keep a little border around the logo since inpainting use nearby pixels to compute the hidden ones.

# string "loc" : Select the part of the picture where is the logo to remove. Same as InpaintFunc loc parameter

# String "alignment" : Alignment of the text. "Top", "Center" and "Bottom" are allowed



# =======================================================
# InpaintFunc
# =======================================================



# Given this function use AVSInpaint.dll and given AVSInpaint is an avisynth C plugin
#don't forget to add loadCplugin("xxx\AVSInpaint.dll") in your script before calling this function !!!




# String "loc" : Select the part of the picture where is the logo to remove.
# See the table :


# ______________ ______________
# | TL | TC |TR | | X1 | X2 |X3 |
# |____|____|___| |____|____|___|
# | ML | MC |MR | or | Y1 | Y2 |Y3 |
# |____|____|___| |____|____|___|
# | BL | BC |BR | | Z1 | Z2 |Z3 |
# |____|____|___| |____|____|___|


# If the logo you want to remove is in the top right corner, then you can choose
# either loc="TR" or loc="x3".

# If you don't want to use one of these preset, you can enter manually the crop values to isolate the logo.
# example : loc = "0,300,-440,-20". Spaces are not allowed in "loc" parameter. You can use function
# InpaintAssist to help you to set crop values.




# String "mask" : Path to the mask of the logo. The mask is a black and white picture. Parties where the logo
# is are white, the others are black.

# example : mask="C:\my_mask.bmp"



# String "mode" : 3 Choices (default both) :

# -Deblend : If the logo is transparent, use this mode.
# -Inpaint : If the logo is opaque, use this mode.
# -Both : If the logo is both opaque and transparent, use this mode.



# Float "AR" : The Sample Aspect Ratio of your video. E.g. : 16/9, 4/3... (Default 1.0).
# This value is used to calculate the PAR of your video. If you don't set this parameter, then
# PAR will be set to 1:1. It's not really important if you don't set this value.
# When you set the AR, take care to add ".0" to your values if you use exact value (16/9 or 4/3).
# example : AR=16.0/9.0 or AR=4.0/3.0



# Int "Speed" : With this parameter you can speed up this function by trimming the clip analyzed by
# AnalyseLogo. A value of 20 means that 100% of clip will be analyzed. With a value of
# 1, only 5% will be analyzed. (min value 1, max value 20, default 5)


# Int "PPMode" : If you want to apply post-processing, 3 modes are available. Default is 0 (disabled)
# -Mode 1 : Blur all the area where logo was present.
# -Mode 2 : Blur all the area where logo was present using TemporalSoften and SpatialSoften.
# -Mode 3 : Blur only the edge of logo area using TemporalSoften and SpatialSoften..


# Int "PP" : Strength of the post-processing. Default is 50 (min value 0, max value 100)
# A 0 value will disable post processing, 100 will process at full strength.

# Bool "Reset" : InpaintFunc contain a feature that allow to not compute logo analysis when it was already done.
# By setting Reset to true, logo analysis is always computed. Default is false.

# Float "radius" : Radius around a damaged pixel from where values are taken when the pixel is inpainted.
# Bigger values prevent inpainting in the wrong direction, but also create more blur.

# Float "sharpness" : Higher values can prevent blurring caused by high Radius values.

# Float "preblur" : Standard deviation of the blur which is applied to the image before the structure tensor is computed.
# Higher values help connecting isophotes which have been cut by the inpainting region, but also
# increase CPU usage. PreBlur=0.0 disables pre-blurring.


# Float "postblur" : Standard deviation of the blur which is applied to the structure tensors before they are used
# to determine the inpainting direction. Higher values help gather more directional information when
# there are only few valid pixels available, but increases CPU usage.


# Bool "show" : Allow the user to see the differents steps of the delogoing. Are displayed the source, the
# repaired, the repaired post-processed, the mask, the repair masks (edge and global), the color
# mask, the alpha mask and the inpaint mask.




#______________________________________________________________________________________

# Function :
#______________________________________________________________________________________


function InpaintFunc( clip clp, string "mask", string "loc", float "AR", string "mode", int "speed",
\ int "pp", int "ppmode", bool "reset", float "radius", float "sharpness", float "preblur",
\ float"postblur", bool "show")

{

mask = default (mask , "" )
loc = default (loc , "" )
AR = default (AR , 1.0 )
mode = default (mode , "both")
speed = default (speed , 5 )
pp = default (pp , 50 )
ppmode = default (ppmode , 0 )
reset = default (reset , false )
radius = default (radius , 8.0 )
sharpness = default (sharpness , 75.0 )
preblur = default (preblur , 8.0 )
postblur = default (postblur , 4.0 )
show = default (show , false )




# debug
# =====


x = width (clp)
y = height (clp)
pp = (pp >= 100) ? 255 : (pp <= 0) ? 0 : int(pp*255/100)
RGB = isRGB(clp)
RGB24 = isRGB24(clp)
RGB32 = isRGB32(clp)
YUY2 = isYUY2(clp)
cropval = (StrLen(loc) != 2 ) ? true : false
spd = (speed != 20 ) ? true : false
PAR = (AR != 1.0) ? float( y) / float( x) * AR : 1.0
bugloc = (loc == "" ) ? true : false
bugmode = (mode != "inpaint" && mode != "deblend" && mode != "both") ? true : false
bugspeed = (speed <= 0 || speed >= 21) ? true : false


assert ( findstr(loc," ") == 0 , """Space character is not allowed in string "loc"."""")
assert ( mask != "" , """You have to define a mask (string "mymask")""")
assert ( bugloc == false , """You must define "Loc".""")
assert ( bugmode == false , """This mode doesn't exist. Change "mode" value.""")
assert ( bugspeed == false , """"Speed" value must be between 1 and 20.""")



# calculation of crop values
# ==========================


null = (cropval == false ) ? eval("""

a = (Rightstr(loc,1) == "L" || Rightstr(loc,1) == "1") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? round((x*1/6))*2 : round((x*1/3))*2
b = (leftstr(loc,1) == "T" || leftstr(loc,1) == "X") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? round((y*1/6))*2 : round((y*1/3))*2
c = (Rightstr(loc,1) == "R" || Rightstr(loc,1) == "3") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? -round((x*1/6))*2 : -round((x*1/3))*2
d = (leftstr(loc,1) == "B" || leftstr(loc,1) == "Z") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? -round((y*1/6))*2 : -round((y*1/3))*2

""") : eval("""

long = StrLen(loc)

posvirg1 = findstr(loc, ",")
posvirg2 = findstr(rightstr(loc,long-posvirg1), ",")
posvirg2 = posvirg2+posvirg1
posvirg3 = findstr(rightstr(loc,long-posvirg2), ",")
posvirg3 = posvirg3 + posvirg2

a = int(value(leftstr(loc,posvirg1-1)))
b = int(value(leftstr(rightstr(loc,long-posvirg1),posvirg2-posvirg1-1)))
c = int(value(leftstr(rightstr(loc,long-posvirg2),posvirg3-posvirg2-1)))
d = int(value(rightstr(loc,long-posvirg3)))
""")


# crop of the part of the image where is the logo + mask creation
# ================================================================


cropped = clp.crop(a,b,c,d)
in = (RGB32 == true) ? cropped : cropped.converttoRGB24()
in2 = (spd == true) ? in.SelectRangeEvery (every=20, length=speed) : in

Masque = imagesource(mask,start=0,end=0).converttoRGB32 # ssS, Changed End=1 to End=0
Masque = Masque.crop(a,b,c,d).levels(127,1,128,0,255)
Masque = Masque.mask(Masque)

BlendedMask = Masque.DirtyBlur().levels(0,1,75,0,255)
BlendedMask = BlendedMask.mask(BlendedMask)
RepairMask = BlendedMask.levels(0,1,255,0,pp)
#RepairEdge = Masque.DirtyBlur().levels(0,1,255,0,900) # ssS fix (removed)
RepairEdge = Masque.DirtyBlur().IPF_Mask() # ssS fix (added)
RepairEdge = RepairEdge.DirtyBlur().levels(0,1,75,0,pp)


# check for an existing computed mask. If it doesn't exist or if reset = true --> computation
# ===========================================================================================


ID = mask + "InpaintFunc" + string(a) + string(b) + string(c) + string(d) + string(speed)

Logo = (reset == true) ? eval("""

in2.analyzelogo(Masque).trim(0,-1).converttoRGB32
imagewriter(ID,0,1,"ebmp")

""") : eval("""

try

{imagesource(ID + "%06d.ebmp",0,0)}
catch (dummy)

{in2.analyzelogo(Masque).trim(0,-1).converttoRGB32
imagewriter(ID,0,1,"ebmp") }""")


# Creation of the masks used for DeblendLogo and InpaintLogo
# ==========================================================


LogoColor = Logo.Crop(0,0,0,Logo.Height/2).converttoRGB24

LogoAlpha = Logo.Crop(0,Logo.Height/2,0,0)
Logoalpha = LogoAlpha.mask(LogoAlpha)

LogoInpaint = LogoAlpha.mask(masque.dirtyblur().levels(0,1,32,0,255))


# InpaintLogo and DeblendLogo are applied depending on the value of "mode"
# ==========================================================================


repaired = (mode == "both") ?
\ in.DeblendLogo(LogoColor,LogoAlpha).
\ InpaintLogo(LogoInpaint,radius=radius,sharpness=sharpness,preblur=preblur,postblur=postblur,PixelAspect=PAR).converttorgb32:
\ (mode == "deblend") ?
\ in.DeblendLogo(Logocolor,Logoalpha).converttorgb32 :
\ in.InpaintLogo(LogoInpaint,radius=radius,sharpness=sharpness,preblur=preblur,postblur=postblur,PixelAspect=PAR).converttorgb32


# Finalization of the repaired with post-processing
# ==========================================================

StainlessS
2nd January 2017, 21:33
InPaintFunc.avs v1.15, Part 2 of 2.


repairedpp = (ppmode == 1) ? repaired.layer(repaired.DirtyBlur( ).mask(RepairMask)) :
\ (ppmode == 2) ? repaired.layer(repaired.DirtyBlur(2).mask(RepairMask)) :
\ (ppmode == 3) ? repaired.layer(repaired.DirtyBlur(2).DirtyBlur().mask(RepairEdge)) : repaired


output = in.converttorgb32.Layer(repairedpp.Mask(BlendedMask))


# Overlay of the cleaned portion over the original clip
# =====================================================


(show == true) ? Eval("""

cropped = cropped.subtitle("source").converttoRGB32
masque = masque.subtitle("mask")

repairmask = repairmask.subtitle("repair mask")
repairedge = repairedge.subtitle("repair edge")

Logoalpha = Logoalpha.subtitle("Logo alpha")
Logocolor = Logocolor.subtitle("Logo color").converttoRGB32
Logoinpaint = Logoinpaint.subtitle("Logo inpaint")

repaired = repaired.subtitle("repaired")
repairedpp = repairedpp.subtitle("repaired pp")

l1 = Stackhorizontal(cropped,repaired,repairedpp)
l2 = Stackhorizontal(masque,repairmask,repairedge)
l3 = Stackhorizontal(logocolor,logoalpha,logoinpaint)

stackvertical (l1,l2,l3)
return spline36resize(last,width(last),height(last))

""") : Eval("""

# v1.15, removed below, ssS
# clp = (RGB32 == true) ? clp : clp.converttoRGB32
# fullclip = clp.layer(output,x=a, y=b)
# fullclip = (RGB == true) ? (RGB32 == true) ? fullclip : fullclip.converttoRGB24() : (YUY2 == true) ? fullclip.converttoYUY2() : fullclip.converttoYV12()
# return fullclip

fullclip = clp.Overlay(output,x=a, y=b) # v1.15, Affect only loc area. ssS.
return fullclip

""")

}


#==========================================================================================================
#==========================================================================================================
#==========================================================================================================


function InpaintAssist ( clip clp, string "loc", string "alignment") {


loc = default (loc, "")
x = width (clp)
y = height (clp)
alignment = default (alignment, "top")
align = (alignment == "top") ? 8 : (alignment == "center") ? 5 : (alignment == "bottom") ? 2 :8
framecount = framecount(clp)


# I "Loc" parameter is not specified, split the clip in 9 parts et show crop value for each part
# ==============================================================================================


loc == "" ? Eval("""

white = blankclip(width=round(x/3),height=round(y/3),color=$FFFFFF,length=framecount)
black = blankclip(width=round(x/3),height=round(y/3),color=$000000,length=framecount)

l1 = stackhorizontal(white,black,white)
l2 = stackhorizontal(black,white,black)
background = stackvertical(l1,l2,l1).converttoRGB32.spline36resize(x,y)
clp = clp.converttoRGB32

a1 = string(0)
a2 = string(round((x*1/6))*2)
a3 = string(round((x*1/3))*2)

b1 = string(0)
b2 = string(round((y*1/6))*2)
b3 = string(round((y*1/3))*2)

ca1 = string(-round((x*1/3))*2)
ca2 = string(-round((x*1/6))*2)
ca3 = string(0)

d1 = string(-round((y*1/3))*2)
d2 = string(-round((y*1/6))*2)
d3 = string(0)

c1 = clp.crop(0 , 0 , -round((x*1/3))*2, -round((y*1/3))*2)
\ .subtitle("TL (" + a1 + "," + b1 + "," + ca1 + "," + d1+ ")",align=8)
c2 = clp.crop(round((x*1/6))*2, 0 , -round((x*1/6))*2, -round((y*1/3))*2)
\ .subtitle("TC (" + a2 + "," + b1 + "," + ca2 + "," + d1+ ")",align=8)
c3 = clp.crop(round((x*1/3))*2, 0 , 0 , -round((y*1/3))*2)
\ .subtitle("TR (" + a3 + "," + b1 + "," + ca3 + "," + d1+ ")",align=8)

c4 = clp.crop(0 , round((y*1/6))*2 , -round((x*1/3))*2, -round((y*1/6))*2)
\ .subtitle("ML (" + a1 + "," + b2 + "," + ca1 + "," + d2+ ")",align=8)
c5 = clp.crop(round((x*1/6))*2, round((y*1/6))*2 , -round((x*1/6))*2, -round((y*1/6))*2)
\ .subtitle("MC (" + a2 + "," + b2 + "," + ca2 + "," + d2+ ")",align=8)
c6 = clp.crop(round((x*1/3))*2, round((y*1/6))*2 , 0 , -round((y*1/6))*2)
\ .subtitle("MR (" + a3 + "," + b2 + "," + ca3 + "," + d2+ ")",align=8)

c7 = clp.crop(0 , round((y*1/3))*2, -round((x*1/3))*2, 0)
\ .subtitle("BL (" + a1 + "," + b3 + "," + ca1 + "," + d3+ ")",align=8)
c8 = clp.crop(round((x*1/6))*2, round((y*1/3))*2, -round((x*1/6))*2, 0)
\ .subtitle("BC (" + a2 + "," + b3 + "," + ca2 + "," + d3+ ")",align=8)
c9 = clp.crop(round((x*1/3))*2, round((y*1/3))*2, 0 , 0)
\ .subtitle("BR (" + a3 + "," + b3 + "," + ca3 + "," + d3+ ")",align=8)

output = stackvertical(stackhorizontal(c1,c2,c3), stackhorizontal(c4,c5,c6), stackhorizontal(c7,c8,c9))
output = output.spline36resize(x,y)
clip1 = background.layer(output.mask(blankclip(output,color=$DEDEDE)))


""") : nop


# If "Loc" is specified, hightlight the part choosen by user
# ==========================================================


(strlen(loc) == 2) ? Eval("""

a = (Rightstr(loc,1) == "L" || Rightstr(loc,1) == "1") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? round((x*1/6))*2 : round((x*1/3))*2
b = (leftstr(loc,1) == "T" || leftstr(loc,1) == "X") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? round((y*1/6))*2 : round((y*1/3))*2
c = (Rightstr(loc,1) == "R" || Rightstr(loc,1) == "3") ? 0 : (Rightstr(loc,1) == "C" || Rightstr(loc,1) == "2") ? -round((x*1/6))*2 : -round((x*1/3))*2
d = (leftstr(loc,1) == "B" || leftstr(loc,1) == "Z") ? 0 : (leftstr(loc,1) == "M" || leftstr(loc,1) == "Y") ? -round((y*1/6))*2 : -round((y*1/3))*2

""") : (strlen(loc) != 0) ? eval("""

long = StrLen(loc)
posvirg1 = findstr(loc, ",")
posvirg2 = findstr(rightstr(loc,long-posvirg1), ",")
posvirg2 = posvirg2+posvirg1
posvirg3 = findstr(rightstr(loc,long-posvirg2), ",")
posvirg3 = posvirg3 + posvirg2

a = int(value(leftstr(loc,posvirg1-1)))
b = int(value(leftstr(rightstr(loc,long-posvirg1),posvirg2-posvirg1-1)))
c = int(value(leftstr(rightstr(loc,long-posvirg2),posvirg3-posvirg2-1)))
d = int(value(rightstr(loc,long-posvirg3)))

""") : nop


(loc != "") ? eval("""

hightlight = blankclip(width=x-a+c,height=y-b+d,color=$96ff2d).converttoRGB32
clip2 = clp.converttoRGB32.layer(hightlight.Mask(blankclip(hightlight, color=$444444)),x=a,y=b)
return clip2.subtitle("Crop value : " + string(a) +", " +string(b) +", " +string(c) +", " +string(d), align=align, size=20 )

""") : clip1


return last
}


#==========================================================================================================
#==========================================================================================================
#==========================================================================================================



function dirtyblur(clip clp, int "mode") {
mode = default (mode, 1)

o = (mode == 1) ? clp.blur(1.58).GeneralConvolution (matrix="40 75 40 75 100 75 40 75 40").blur(1.58).blur(1.58).blur(1.58) :
\ clp.converttoYUY2.temporalsoften(1,64,64,mode=2,scenechange=6).spatialsoften(2,255,255).converttoRGB32

return o
}

Function IPF_Mask(clip c) { # ssS fix (added), Correction for fixed Levels bug. Returns RGB32
c.ShowGreen(pixel_type="YV12").Mt_Lut(Mt_Polish("(x >= 164) ? 0 : x"))
Return MergeRGB(Last,Last,Last).Levels(0,1.0,255,0,900)
}


Mod in blue

VoodooFX
22nd June 2019, 20:41
Can someone check if InpaintFunc.avs(1.13-1.15) crash AviSynth+? "Inpaint" mode works ok, "Deblend" and "Both" modes instantly crash AviSynth+.
No problems with AviSynth 2.6.

Report from AVSMeter:
AviSynth+ 0.1 (r2772, MT, i386) (0.1.0.0)
Exception 0xC0000005 [STATUS_ACCESS_VIOLATION]
Module: C:\Windows\SysWOW64\VCRUNTIME140.dll
Address: 0x72DC282E

Groucho2004
22nd June 2019, 20:43
Can someone check if InpaintFunc.avs (all versions) crash AviSynth+? "Inpaint" mode works ok, "Deblend" and "Both" modes instantly crash AviSynth+.
No problems with AviSynth 2.6.

Report from AVSMeter:
AviSynth+ 0.1 (r2772, MT, i386) (0.1.0.0)
Exception 0xC0000005 [STATUS_ACCESS_VIOLATION]
Module: C:\Windows\SysWOW64\VCRUNTIME140.dll
Address: 0x72DC282EPost your script.

VoodooFX
22nd June 2019, 20:45
How to quickly test it:
1) video file (short!)
2) bmp file (RGB24, same resolution as video, all solid black and small solid white "blob" at top-left corner.
3) InpaintFunc.avs and AVSInpaint.dll ( http://avisynth.nl/index.php/InpaintFunc )
4) script:
LoadCplugin("C:\AVSInpaint.dll")
Import("C:\InpaintFunc.avs")
InpaintFunc(mask="c:\test.bmp", loc="tl",mode="Inpaint",speed=1)

Groucho2004
22nd June 2019, 20:58
How to quickly test it:
1) video file (short!)
2) bmp file (RGB24, same resolution as video, all solid black and small solid white "blob" at top-left corner.
3) Inpaint.avs and AVSInpaint.dll ( http://avisynth.nl/index.php/InpaintFunc )
4) script:
LoadCplugin("C:\AVSInpaint.dll")
Import("C:\InpaintFunc.avs")
InpaintFunc(mask="c:\test.bmp", loc="tl",mode="Inpaint",speed=1)I can reproduce this, VDub also reports an access violation. However, my culprit is avisynth.dll, not VCRUNTIME140.dll.

Works fine with classic Avisynth 2.6. You should post this in the AVS+ thread.

Edit: Apparently there's a fix from StainlessS, just read a few posts above.

VoodooFX
22nd June 2019, 21:17
Both v1.14 & v1.15 StainlessS scripts crash too.

hello_hello
23rd June 2019, 17:59
ImageSource is a built-in Avisynth function, isn't it?

Using Avisynth 2.6 it works fine, but when I try to open the same script with MeGUI and it's portable Avisynth+ (on XP).

InpaintFunc(mask="d:\test.bmp", loc="TL",mode="Inpaint",speed=1)

https://i.postimg.cc/SKTj93Qk/Inpaint-Func.gif

Groucho2004
23rd June 2019, 18:56
ImageSource is a built-in Avisynth function, isn't it?

Using Avisynth 2.6 it works fine, but when I try to open the same script with MeGUI and it's portable Avisynth+ (on XP).

InpaintFunc(mask="d:\test.bmp", loc="TL",mode="Inpaint",speed=1)

https://i.postimg.cc/SKTj93Qk/Inpaint-Func.gifIn AVS+, ImageSource() was transferred to a plugin ("ImageSeq.dll").

VoodooFX
23rd June 2019, 20:18
ImageSource is a built-in Avisynth function, isn't it?

Using Avisynth 2.6 it works fine, but when I try to open the same script with MeGUI and it's portable Avisynth+ (on XP).

InpaintFunc(mask="d:\test.bmp", loc="TL",mode="Inpaint",speed=1)

https://i.postimg.cc/SKTj93Qk/Inpaint-Func.gif

I noticed that ImageSource & ImageWriter doesn't work with portable MeGUI's avs+ without manually loading ImageSeq.dll. You should ask why it is not auto-loaded in MeGUI's thread.

hello_hello
24th June 2019, 06:40
I noticed that ImageSource & ImageWriter doesn't work with portable MeGUI's avs+ without manually loading ImageSeq.dll. You should ask why it is not auto-loaded in MeGUI's thread.

I did check the Avisynth Wiki but didn't see any mention of it being a separate dll for Avisynth+. I don't know if it's a good idea to put it in the Avisynth 2.6 auto-loading plugin folder.

I added
LoadPlugin("C:\Program Files\MeGUI\tools\avs\plugins\ImageSeq.dll")
to the script and it still opened fine with the installed Avisynth 2.6.
When I tried to open it with MeGUI and the portable Avisynth+ it was okay for mode="InPaint" but MeGUI crashed when I tried mode="both".

So I assume it happens on XP too, but unfortunately I didn't discover anything new.

Edit: I tried the backup copy of an older ImageSeq.dll version in the MeGUI/avs/plugins folder, dated 2018/07/02, but the result was the same.

Edit: In case it hasn't been mentioned, InPaintFunc appears to create the ebmp file normally when using Avisynth+ (loading the script causes MeGUI to check it, which in turned causes the ebmp file to be created). It doesn't crash MeGUI until I try to preview the script after the ebmp file has been created.
I tried being more specific about the location of the logo with loc="0,0,-1604,-764" (1080p source, top left) but nothing changed.

Edit: In case it means something to someone, I commented out the InPaintFunc line, added the script to MeGUI's job queue, uncommented InPaintFunc and ran the job. The error appearing in MeGUI's log file was:
"Process exits with error: 0xC0000005 STATUS_ACCESS_VIOLATION (-1073741819)"

StainlessS
24th June 2019, 16:04
0xC0000005 STATUS_ACCESS_VIOLATION

Often happens if code tries to access memory location 0, ie bug in dll.

EDIT: Yep, from Devs forum on same dll:- https://forum.doom9.org/showthread.php?p=1877829#post1877829

EDIT: The plugin somehow clears or is overwriting an existing framebuffer pointer?
The crash itself occurs at an internal RGB24-RGB32 conversion but since the destination frame does not exist (zero pointer) it will show "access violation".
I'll have a look at the dll source.

pinterf
24th June 2019, 16:12
Obviously there was a bug, see test build here (also x64)
https://drive.google.com/open?id=1AQ1ZmRvVbGhXuL_xxuGX2ukXE4Uy7nWV

hello_hello
25th June 2019, 05:57
Obviously there was a bug, see test build here (also x64)
https://drive.google.com/open?id=1AQ1ZmRvVbGhXuL_xxuGX2ukXE4Uy7nWV

So far, so good here (XP).

Thank you very much!

pinterf
25th June 2019, 09:28
Moved to git, real release:
AvsInPaint v1.1 (20190624)
https://github.com/pinterf/AvsInpaint/releases


- Fix crash in AVSInpaint-2008.02.23, when using mode "Deblend" or "Both"
(double frame release, revealed when using Avisynth+)
- Add version resource
- Visual Studio 2019 solution
- Moved to Avisynth C 2.5 interface
- x64 version
- (no new colorspaces)

VoodooFX
25th June 2019, 14:36
I updated wiki of http://avisynth.nl/index.php/InpaintFunc with newer versions of InpaintFunc and requirements.

fAy01
26th June 2019, 23:53
Moved to git, real release:
AvsInPaint v1.1 (20190624)
https://github.com/pinterf/AvsInpaint/releases


- Fix crash in AVSInpaint-2008.02.23, when using mode "Deblend" or "Both"
(double frame release, revealed when using Avisynth+)
- Add version resource
- Visual Studio 2019 solution
- Moved to Avisynth C 2.5 interface
- x64 version
- (no new colorspaces)

https://github.com/pinterf/AvsInpaint/commit/3ee1f51183e446186aefd35578146603d3b66fc7
Is 2.5 a typo?

Groucho2004
27th June 2019, 00:35
Is 2.5 a typo?No, C 2.5 interface is the latest. You may be thinking of the C++ interface.

fAy01
27th June 2019, 00:40
No, C 2.5 interface is the latest. You may be thinking of the C++ interface.

I see. Thanks for clarifying.

hello_hello
27th June 2019, 07:42
I probably should have checked before assuming, but I didn't test the new AVSInPaint build with Avisynth 2.6. It may be an XP-only issue, however it's working with Avisynth+, but not Avisynth 2.6. It applies to version 1.1 Beta and version 1.1.
I can't imagine why I wouldn't have checked the beta version with Avisynth 2.6, but obviously I didn't as it prevents Avisynth 2.6 from loading.

I didn't have VS 2019 installed, but installing it didn't change anything. Rebooting didn't help. Unless it's more than an XP problem, I can probably load the appropriate dll as required (the old version for Avisynth 2.6 and the new version for Avisynth+).

I have the following script in the Avisynth 2.6 auto-loading folder, and the result is below. I've also tried LoadCPlugin and LoadPlugin.

Anyone else tested with Avisynh 2.6?

AVSInpaint = "C:\Program Files\AviSynth\C Plugins\AvsInPaint.dll"
exist(AVSInpaint) ? Load_Stdcall_Plugin(AVSInpaint) : nop()

https://i.postimg.cc/7hntmbp9/v1-1.gif

Edit: For anyone else who may need it, I'm currently making AVSInPaint work for the installed Avisynth 2.6 and MeGUI's Avisynth+ by adding the following avsi script to the installed Avisynth/plugins folder. No need to manually load ImageSeq.dll for Avisynth+ either. Edit the file paths and dll names to suite.

IsAvisynthPlus = (FindStr(LCase(VersionString), "avisynth+") > 0)

ImageSeq = "C:\Program Files\MeGUI\tools\avs\plugins\ImageSeq.dll"
IsAvisynthPlus && exist(ImageSeq) ? LoadPlugin(ImageSeq) : nop()

AVSInPaintNew = "C:\Program Files\AviSynth\C Plugins\AVSInPaint 1.1.dll"
IsAvisynthPlus && exist(AVSInPaintNew) ? LoadCPlugin(AVSInPaintNew) : nop()

AVSInPaintOld = "C:\Program Files\AviSynth\C Plugins\AVSInPaint 2008-02-23.dll"
!IsAvisynthPlus && exist(AVSInPaintOld) ? Load_Stdcall_Plugin(AVSInPaintOld) : nop()

Groucho2004
27th June 2019, 07:46
I have the following script in the Avisynth 2.6 auto-loading folder. And the result is below. Anyone else tested with Avisynh 2.6?

AVSInpaint = "C:\Program Files\AviSynth\C Plugins\AvsInPaint.dll"
exist(AVSInpaint) ? Load_Stdcall_Plugin(AVSInpaint) : nop()

https://i.postimg.cc/7hntmbp9/v1-1.gif
Why are you loading it as a 2.0 plugin? Did you miss that the C interface has been updated to 2.5? Change Load_Stdcall_Plugin() to LoadCPlugin() and it should work.

hello_hello
27th June 2019, 08:19
Why are you loading it as a 2.0 plugin? Did you miss that the C interface has been updated to 2.5? Change Load_Stdcall_Plugin() to LoadCPlugin() and it should work.

I've also tried LoadCPlugin and LoadPlugin.

I've even tried pleading, but still no go.
Load_Stdcall_Plugin() works with Avisynth+.

Groucho2004
27th June 2019, 08:35
I've even tried pleading, but still no go.
Load_Stdcall_Plugin() works with Avisynth+.Do you have avisynth_c.dll in your auto-load directory? If so, remove it. Also, use the Avisynth Info Tool (https://forum.doom9.org/showthread.php?t=176079) to check your installation and post the log.

hello_hello
27th June 2019, 09:24
There's no avisynth_c.dll.

If by "post the log file" you mean use the "Save Info" button, this is everything when I use the script I posted earlier to try and auto-load the new AVSInPaint:

Not An Avisynth 2 C Plugin: C:\Program Files\AviSynth\C Plugins\AVSInPaint 1.1.dll
(Audio Load Additional Plugins.avsi, line 23)

I'm still successfully loading Yadif.dll and ffavisynth.dll the same way. And of course the old AVSInPaint.

When I don't try to load it there's no errors except one. Edit: See the next post for the "full" log.

As a side note, when I prevent Avisynth 2.6 from trying to load the new AVSInPaint, this is the single error.

LoadPlugin: unable to load "C:\Program Files\AviSynth\plugins\VSFilter 3.1.0.801.dll", error=0x3e6

Any idea what error 0x3e6 means? I ask because it's an odd one. If I remember correctly, VSFilter will load when opening scripts with MPC-HC, but not MeGUI (even with Avisynth 2.6). If I remember correctly, I have to manually load an old version for MeGUI. It won't even manually load the new one from the plugins folder. It seems a bit odd and I've never discovered why, but it's been a while so I'd have to check all that.
I did remove VSFilter 3.1.0.801.dll from the plugins folder and ran Info Tool again, just in case it was causing oddness, but nothing changed, except then no there were no errors (unless I tried to load AVSInPaint).